오류를 처리하는 가장 발전적이고 효과적인 방법이 C++ 예외 처리 기능입니다.
그런데 VC++ (6 or 7)의 설명서에 약간 오해의 소지가 있는 부분이 있습니다.
예를 들어,

try 
{ 
    int* p = 0; 
    *p = 0; 
} 
catch (...) 
{ 
    // do something 
} 

이렇게 하면, 위 *p = 0 줄에서 access violation 예외가 발생하고
그 예외가 아래 catch 블럭에서 잡힙니다.

문제는 debug 빌드인 경우에는 예상대로 예외 처리가 되는데
release 빌드일 때는 그렇지 않다는 데 있습니다.

MSDN이나 VC++ 도움말에서 예외 처리에 관련된 부분을 보면
항상 컴파일러 옵션 /GX 또는 /EHsc를 지정하라는 말이 나옵니다.
"win32 structured exception" 방식을 쓰려면 /GX 없이 그냥 컴파일하고
C++ 예외 처리 방식을 쓰려면 /GX로 컴파일하라..." 이런 식으로 설명되고 있죠.

디폴트 옵션도 /EHsc 입니다.
/EHs 는 syncronous 예외 처리 모델을 가리키고
/EHc 는 C 함수는 예외를 throw하지 않는 다고 가정하는 것을 가리킵니다.

syncronous 모델은 뭐냐하면, 명시적으로 throw가 사용되지 않은 함수에 대해서는
예외 처리에 대한 지원을 하지 않는 것을 말합니다.

따라서

try 
{ 
    int* p = 0; 
    *p = 0; 
} 
catch (...) 
{ 
    // do something 
} 

이런 프로그램은 디버그 빌드일 때는 잘 돌아가고
예외 처리도 잘 되고,
잘못된 동작이 있을 때 이쁘게 메시지 박스 띄우고 부드럽게 종료하고
다 잘 됩니다.

그러다가 릴리즈 빌드로 바꾸면 디폴트로 /EHsc 옵션이 먹으면서
예외 처리도 안 되고
access violation 같은 거 발생할 때 프로그램이 죽어버립니다.

해결책은 단순하죠.
컴파일러 옵션 대화상자에서 C++ 예외 처리를 사용하지 않음으로 선택하고
직접 /EHa 옵션을 추가해주면 됩니다.

/EHa 옵션을 주고
메인 프로그램 진입점을

try 
{ 

} 
catch (...) 
{

} 

이런 블럭으로 감싸면 프로그램이 예기치 않게 종료되는 일을 방지할 수 있습니다.
위 내용은 VC6, VC7 공통입니다.
이상입니다.

** 경고
예외 처리는 복잡한 고려사항이 많기 때문에
충분히 공부한 후 사용해야 합니다.
예외 처리는 체계적으로 사용해야만 효과적이며
그렇지 않으면 부작용이 더 클 수 있습니다.

posted by 뚱2