Visual Studio에서 예외 필터 함수 디버깅
먼저 다음 코드를 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
LONG WINAPI MyUnFilter(struct _EXCEPTION_POINTERS *lpExceptionInfo); int main() { LPBYTE lpBuff = nullptr; SetUnhandledExceptionFilter(MyUnFilter); *lpBuff = 11; return 0; } LONG WINAPI MyUnFilter(struct _EXCEPTION_POINTERS *lpExceptionInfo) { DWORD dwExceptCode = lpExceptionInfo->ExceptionRecord->ExceptionCode; LONG lResult; if (dwExceptCode == EXCEPTION_ACCESS_VIOLATION) printf("access violation caught by MyUnFilter\n"); else lResult = EXCEPTION_CONTINUE_SEARCH; return lResult; } |
디버거로 실행하면 다음처럼 처리하지 않은 예외가 있다며 알려 준다.
필터 함수를 등록했으므로 계속 진행해 필터 함수를 디버깅하고 싶지만 Visual Studio 디버거에서 놓아 주지 않는다. 예외 설정에서 해제하면 괜찮을까 시도해 봐도 전혀 신경쓰지 않고 처리하지 않은 예외라며 끝까지 붙잡아 두는 그 노력에 우선 경의를 표하자.
처리하지 않은 예외를 알려 주는 건 좋지만 이래서는 필터 함수를 디버깅할 방법이 없다. 이를 해결하려면 다음 두 방법 정도를 생각할 수 있다.
- 예외 발생 지점을
__try
구역으로 감싸고__except
에서 필터 함수를 직접 호출 IsDebuggerPresent()
를 이용해 디버거를 붙임
첫 번째는 대략 다음과 같다. 즉 호출하는 쪽에서 코드를 고친다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int main() { LPBYTE lpBuff = nullptr; SetUnhandledExceptionFilter(MyUnFilter); __try { *lpBuff = 11; } __except(MyUnFilter(GetExceptionInformation())) { exit(1); } return 0; } |
두 번째는 호출하는 쪽을 그대로 두고 필터 함수를 고친다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
LONG WINAPI MyUnFilter(struct _EXCEPTION_POINTERS *lpExceptionInfo) { if (!IsDebuggerPresent()) { printf("pause\n"); getchar(); } DWORD dwExceptCode = lpExceptionInfo->ExceptionRecord->ExceptionCode; LONG lResult; if (dwExceptCode == EXCEPTION_ACCESS_VIOLATION) printf("access violation caught by MyUnFilter\n"); else lResult = EXCEPTION_CONTINUE_SEARCH; return lResult; } |
이때는 디버거에서 실행하지 않고 디버그 모드로 빌드한 실행 파일을 바로 실행한다. 당연히 예외가 발생해 필터 함수로 진입한다. IsDebuggerPresent()
는 디버거로 실행 중이면 true
를 반환하는데 직접 실행했으므로 if
구역을 실행하고 getchar()
에서 키 입력을 기다린다. 이때 Visual Studio Debug 메뉴에서 Attach to Process…를 실행해 해당 프로세스에 디버거를 붙이면 된다.
정리하면, 첫 번째는 호출하는 쪽을 바꿔야 하고 두 번째는 디버거를 따로 붙여야 하는 점이 번거로우므로 상황에 맞춰 쓰면 되겠다.