리소스를 정리하기 전에 예외가 발생한 경우

동적할당등을 받은 메모리가 아직 해제가 안된 상태에서 예외처리에 의한 함수 종료는 심각한 메모리 누수 현상을 가져올 수 있다.

#include 

using namespace std;

void A();
void B();
void C();

int main()
{
    try
    {
        A();
    }
    catch(int ex)
    {
        cout << "예외 처리" << endl;
    }
}

void A()
{
    // 메모리를 할당
    char* p = new char [100];   // 메모리를 100바이트 할당

    // 여기까지 실행
    cout << "예외가 발생하기 전" << endl;
    B();

    // 이곳은 실행하지 않음을 출력
    cout << "예외가 발생한 후" << endl;
    delete[] p;
    p = NULL;
}

void B()
{
    throw "Exception!!";
}
  • 위 소스는 A() 함수의 앞에서 할당된 메모리가 해제되지 않는 문제가 발생.
  • 함수 끝에서 무언가 정리 작업을 해주는 경우가 있다면 모두 이 문제점에 노출

소멸자로 리소스 문제 해결하기

  • 함수 소멸시 함수안의 모든 변수 및 객체가 소멸
  • 객체는  소멸시 소멸자를 호출하는 방법을 이용
  • 이점을 이용, 리소스를 해제하는 용도의 클래스를 제작
  • 이것을 스마트 포인터라 부른다.
#include 

using namespace std;

class SmartPointer
{
public:
    SmartPointer(char* p)
        :ptr(p)
        {
            
        }
    ~SmartPointer()
        {
            // 소멸자가 호출되는 것을 확인한다.
            cout << "메모리가 해제된다." << endl;

            delete[] ptr;
        }
public:
    char* const ptr;
};

void A();
void B();

int main()
{
    try
    {
        A();
    }
    catch(const char* ex)
    {
        cout << "예외 처리" << endl;
    }

    return 0;
}

void A()
{
    // 메모리를 할당
    char* p = new char [100];   // 메모리를 100바이트 할당

    // 메모리를 스마트 포인터로 보관한다
    SmartPointer sp(p);

    // 예외를 던지는 함수 호출
    B();

    // 이곳은 실행하지 않음을 출력
    cout << "예외가 발생한 후" << endl;
    
   
    // delete[] p;
    // p = NULL;
}

void B()
{
    throw "Exception!!";
}
  • 함수가 정상적으로, 또는 예외에 의해서 종료된 경우 모두 스마트 포인터 객체 sp의 소멸자를 호출한다.
  • 소멸자단에서 메모리 해제등을 시켜주기 때문에 따로 신경쓰지 않아도 되게 된다.

주의 해야 할 점은 다음과 같다.

  • 생성자가 올바르게 종료된 경우만 객체를 생성한 것으로 간주한다.
  • 생성자에서 예외가 발생한 경우라면 정상적으로 종료된게 않은 것이고  객체도 생성되지 않은 것이다.
  • 객체가 생성되지 않았으니 소멸자도 호출될 일이 없다.
  • 결국 생성자단에서 일어난 메모리 누수를 해결하기 위한 예외를 다시 던져야 한다.

소멸자에서의 예외는 반드시 막아야 한다.

  • 객체의 소멸자에서 예외가 던져지는 경우 프로그램이 비정상 종료할 수 있다.
  • 소멸자 밖으로는 예외가 던져지지 않게 막아야 한다.
  • 생성자에서 했던 것처럼 소멸자의 모든 코드를 try블록으로 감쌀 필요가 있다.
  • 잡아낸 예외는 절대로 소멸자 밖으로 다시 던져서는 안 된다

저작자 표시
신고

'컴퓨터 언어 > C++' 카테고리의 다른 글

파일 입출력  (0) 2012.12.28
예외 처리, 예외에 안전한 코드 만들기  (0) 2012.12.24
예외 처리, 함수 깊숙히  (0) 2012.12.24
예외 처리  (0) 2012.12.21
오버라이딩  (0) 2012.12.20
가상함수를 이용한 다형성 구현  (0) 2012.12.20