EC++ 항목 08 - 예외가 소멸자를 떠나지 못하도록 붙들어 놓자
in Development on C++
예외가 소멸자를 떠나지 못하도록 붙들어 놓자
이것만은 잊지말자 1
소멸자에서는 예외가 빠져나가서는 안됩니다.
소멸자 안에서 호출된 함수가 예외를 던질 가능성이 있다면,
소멸자에서 삼켜 버리던지, 프로그램을 끝내든지 해야 된다.
stack unwinding
소멸자 밖으로 예외가 전파되면 가장 문제가 되는 건 stack unwinding
관련된 문제다.
일반적으로 예외가 발생하면, catch 문까지 stack이 되감기면서 로컬 변수들의 소멸자를 호출한다.
소멸자에서 다시 한 번 예외가 발생하면 프로그램은 무조건 crash
가 발생하게 된다.
프로그램 종료
DBConn::~DBConn
{
try{ db.close(); }
catch (...)
{
close 로그 작성
std::abort();
}
}
소멸자에서 삼키기
참고로 예외를 삼키는 방법을 사용하려면, 예외 발생과 상관없이 프로그램이 정상 동작 할 수 있도록 reliable
해야 한다.
DBConn::~DBConn
{
try{ db.close(); }
catch (...)
{
close 로그 작성
}
}
이것만은 잊지말자 2
어떤 예외에 대해 사용자가 반응해야 한다면,
해당 연산을 제공하는 함수는 보통 함수여야 한다.
위에서 봤던 예외 삼키기, 프로그램 종료하기 보다 더 좋은 전략은 다음과 같다.
바로 - 예외에 대처할 기회를 사용자에게 준다.
DB를 닫는 close 함수
를 사용자에게 제공하고,
소멸자에서는 DB가 열려있는 경우에만 close를 호출한다.
이를 통해 사용자에게 에러를 처리할 수 있는 기회
를 줄 수 있다.
이 방법의 핵심은 예외가 발생할 가능성이 있다면, 그 예외는 소멸자가 아닌 일반 함수에서 비롯되어야 한다는 것이다.
아래 코드에서 소멸자에서 예외가 발생하는 것보단 사용자가 close() 함수를 호출 했을 때 예외가 발생하는 게 더 나은 설계이다.
void close()
{
db.close();
close = true;
}
DBConn::~DBConn
{
if( !closed)
{
try{
db.close();
}
catch (..){
close 로그 작성
}
}
}