728x90
반응형

제목의 의미는 소멸자에서 예외가 빠져나오지 않도록 처리하자는 것을 의미한다.

 

소멸자가 호출되는 경우

  • 정상적으로 객체가 종료되었을 때
  • 예외처리 메커니즘에 의해 객체가 소멸될 때

위에서 예외처리 메커니즘에 의해 객체가 소멸될 때 또 예외가 발생한다면, terminate함수가 호출되어 프로그램이 종료된다. 따라서 try~catch로 예외를 소멸자 내에 묶어 두어야 한다.

아래의 코드를 보면,

class DBConnection
{
public:
	static DBConnection create(); // DB 생성
	void close(); // 연결 닫기
}

----
class DBConn
{
public:
	~DBConn()
	{
		db.close(); // DB 연결 닫기
	}
    
private:
	DBConnection db;
}

DBConn이 소멸할 때 db.close를 호출하며 이때 예외가 발생한다면 프로그램은 미정의 동작을 발생시킬 것이다.

따라서 위의 해결 방법대로 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;
}

위와 같이 예외 발생 시 그 예외는 소멸자가 아닌 다른 함수에서 호출되어야 한다.

이렇게 된다면 사용자가 에러가 발생할만한 가능성이 있는 코드를 원하는 타이밍에 호출할 수 있으므로 에러에 잘 대처할 수 있다.

 

요약

  • 소멸자에서는 예외가 빠져나가면 안 된다. 만약 소멸자 안에서 호출된 함수가 예외를 던질 가능성이 있다면, 어떤 예외이든지 소멸자에서 모두 받아낸 후에 무시하거나 프로그램을 끝내거나 해야 한다.
  • 어떤 클래스의 연산이 진행되다가 던진 예외에 대해 사용자가 반응해야 할 필요가 있다면, 해당 연산을 제공하는 함수는 반드시 보통의 함수(즉, 소멸자가 아닌 함수)이어야 한다.

 

728x90
반응형