개요
졸작으로 C++ 서버를 만들면서 제일 잣같았던 부분은, Try-Catch로 모든 Exception을 캐치 할 수 없다는 것이다.
특히 밥먹듯이 발생하던 "잘못된 메모리 접근"이 골치아팠는데, 그에 대한 해결 방법 중 하나인 Unhandled Exception Dump를 따는 법을 간단하게 적어보겠다.
Try-Catch가 안되는 Exception
void CreateException(int* a = nullptr) {
a[100] = 100;
}
...
try
{
CreateException(); // 강제로 Memory Access Exception 유발.
}
// Memory Access Exception은 Catch되지 않는다.
catch (...)
{
cout << "Wow" << endl;
}
cout << "Success" << endl;
// 결과 : 아무 메세지가 출력되지 않음.
위 코드에서 try-catch를 사용하여 이상한 메모리 접근 시도를 감쌌는데도 아무 출력없이 프로그램이 죽어버리는 것을 볼 수 있다.
Unhandled Exception(관리 안되는 예외) 잡기
LONG WINAPI ExceptionCallBack(EXCEPTION_POINTERS* exceptionInfo) {
cout << "Exception!" << endl;
return 0L;
}
int main()
{
// Exception 콜백을 등록해준다.
SetUnhandledExceptionFilter(ExceptionCallBack);
try
{
CreateException(); // 강제로 Memory Access Exception 유발.
}
// Memory Access Exception은 Catch되지 않는다.
catch (...)
{
cout << "Wow" << endl;
}
cout << "Success" << endl;
}
// 결과 : "Exception!"이 출력됨
여러가지 방법이 더 있는 것으로 보이지만, 위 함수를 쓰면 간편하게 Unhandled Exception의 콜백 함수를 등록 할 수가 있다.
여기서 해당 Exception의 원인을 좀 더 트래킹하고 싶다면 아래처럼 하면 된다.
Mini Dump를 사용하기
#include <iostream>
#include <Windows.h>
#include <DbgHelp.h>
__declspec(noinline) void CreateException(int* a = nullptr) {
a[100] = 100;
}
LONG WINAPI ExceptionCallBack(EXCEPTION_POINTERS* exceptionInfo) {
MINIDUMP_EXCEPTION_INFORMATION info = { 0 };
info.ThreadId = ::GetCurrentThreadId(); // Threae ID 설정
info.ExceptionPointers = exceptionInfo; // Exception 정보 설정
info.ClientPointers = FALSE;
std::wstring stemp(L"test.dmp");
HANDLE hFile = CreateFile(stemp.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// 위에서 받은 내용들을 토대로 덤프 파일을 만든다.
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &info, NULL, NULL);
cout << "Exception!" << endl;
return 0L;
}
int main()
{
// Exception 콜백을 등록해준다.
SetUnhandledExceptionFilter(ExceptionCallBack);
try
{
CreateException(); // 강제로 Memory Access Exception 유발.
}
// Memory Access Exception은 Catch되지 않는다.
catch (...)
{
cout << "Wow" << endl;
}
cout << "Success" << endl;
}
// 결과 : "Exception!"이 출력됨
미니 덤프를 사용해서 덤프파일을 만든 뒤, 확인해보면 아래와 같은 방법으로 어디서 오류가 났는지 까지 찾아낼수가 있다.
C# 에도 비슷한 기능으로 Unhandledexception이 있는데 참고하면 좋을 듯 하다.
'Programming > C++ & Unreal' 카테고리의 다른 글
직렬화 라이브러리 완성! (0) | 2020.02.24 |
---|---|
C++ region (0) | 2020.02.20 |
C++ config parser (0) | 2019.05.26 |
언리얼4 C++ 에셋 불러오기 (0) | 2019.05.15 |
언리얼(C++)에서 자주 사용하는 매크로 (언리얼 로그 찍기) (0) | 2019.05.09 |