책 정리/Effective C++ 3rd
항목 8. 예외가 소멸자를 떠나지 못하도록 붙들어 놓자
ocean20
2019. 12. 17. 11:14
말그대로 예외 동작이 소멸자 내에서 종료되어야 함을 의미한다.
1. 소멸자가 호출되는경우
(1) 정상적으로 객체가 종료되었을때
(2) 예외처리 메커니즘에 의해 객체가 소멸될때
(2)와 같이 예외처리 메커니즘에 의해 객체가 소멸될때 또 예외가 발생한다면, terminate함수가 호출되어 프로그램이 종료된다. 따라서 try catch로 예외를 소멸자내에서 묶어두어야 한다.
일반적으로 c++은 예외를 내보내는 소멸자를 좋아하지 않는다!!라고 생각하자.
자 우선 이 코드를 봐보자.
class DBConnection {
public :
...
static DBConnection create();
void close();
};
class DBConn {
public :
...
~DBConn()
{
db.close(); //여기서 예외발생시 소멸자에서 예외가 나가도록 내버려둔다.
}
private:
DBConnection db;
};
위 코드에서 DBConn객체에 예외가 발생하여 ~DBConn()호출을 하였고, 여기서 또 예외발생시, 프로그램이 미정의 동작을 발생시킬것이다.
TIP). try catch로 예외를 소멸자에 묶어보자.
해결방법 1. 프로그램을 바로 끝낸다.
DBConn::~DBConn()
{
try{db.close();}
catch(…){
//close 호출이 실패했다는 로그를 작성합니다;
std::abort();
}
}
해결방법 2. 예외를 삼켜버린다.
DBConn::~DBConn()
{
try { db.close(); }
catch(…){
//close 호출이 실패했다는 로그를 작성합니다;
}
}
위 경우는 예외를 삼킨 이후에도 프로그램의 정상동작이 보장되어야 빛을 볼것이다.
해결방법3. 문제 대처기회를 사용자에게 선 제공하자. 책임전가 해버리자.
따라서 예외 발생시 그 예외는 소멸자가 아닌 다른 함수에서 비롯되어야 한다.
예외를 일으키는 소멸자는 시한폭탄이다.!!!
class DBConn{
public :
void close()
{
db.close();
closed = true;
}
~DBConn()
{
if(!closed)
try{
db.close();
}
catch(...){
//close 호출이 실패했습니다. 로그작성
...
}
private:
DBConnection db;
bool closed;
};
이것만은 잊지 말자!
1. 소멸자에서 예외를 묶어두자. 방법은 삼키던가 프로그램 강제종료시키던가
2. 예외가 발생하는 함수는 보통의 함수여야 한다.(소멸자가 아닌 함수)