MFC

Release 모드에서 오류 발생 시 자동 덤프 생성에서 분석까지...

의찬 2015. 12. 24. 17:25

개발을 하다보면 Release 모드 상태에서 어느 순간 오류가 발생하는 경우가 생길 수 있다.

덤프 생성 및 분석을 위하여 해야할 일은 아래와 같다.

먼저 pdb 및 map 파일이 빌드 시 생성되도록 프로젝트 설정을 바꿔야 한다

1. C/C++ -> 일반 -> 디버그 정보 형식 에서 "프로그램 데이터베이스(/Zi)" 로 바꾼다.

2. C/C++ -> 일반 -> 명령줄 -> 추가옵션 에서 /Zo 를 추가한다

3. C/C++ -> 출력 파일 -> 어셈블러 출력 에서 "어셈블리, 기계어 코드, 소스"로 변경한다

4. 링커 -> 디버깅 -> 디버그 정보 생성 에서 "예" 선택

5. 링커 -> 디버깅 -> 맵 파일 생성 에서 "예" 선택

5. 생성된 dmp 파일을 pdb 파일 exe 파일과 같은 폴더에 넣고 분석한다

 

이렇게 하면 디버그 모드로 실행시에 변수 값과 오류 위치를 알 수 있다.

하지만. 릴리즈 모드로 실행 시 최적화 옵션이 걸려 있으면 변수 값이 나오지 않는 경우가 생길 수 있다.

이럴 경우 최적화 옵션을 잠시 꺼두고 프로그램을 실행하면 오류 위치와 메모리 값을 같이 보면서 디버깅 할 수 있다.

 

stdafx.h 에서 아래 추가

 

#include "dbghelp.h"

typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
 CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
 CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
 CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);

extern LONG TopExceptionFilter(LPEXCEPTION_POINTERS pExp);

 

stdafx.cpp 에서 아래 추가

 

LONG TopExceptionFilter(LPEXCEPTION_POINTERS pExp)
{
 LONG retval = EXCEPTION_CONTINUE_SEARCH;
 HMODULE hDll = NULL;
 hDll = ::LoadLibrary(_T("DBGHELP.DLL"));
 TCHAR filename[32];
 COleDateTime ct = COleDateTime::GetCurrentTime();
 swprintf_s(filename, L"crash_%04d%02d%02d_%02d%02d%02d.dmp", ct.GetYear(), ct.GetMonth(), ct.GetDay(), ct.GetHour(), ct.GetMinute(), ct.GetSecond());

 if (hDll)
 {
  MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll, "MiniDumpWriteDump");
  if (pDump)
  {
   HANDLE hFile = ::CreateFile(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
   if (INVALID_HANDLE_VALUE != hFile)
   {
    _MINIDUMP_EXCEPTION_INFORMATION ExInfo;

    ExInfo.ThreadId = ::GetCurrentThreadId();
    ExInfo.ExceptionPointers = pExp;
    ExInfo.ClientPointers = NULL;

    
    BOOL bOK = pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpWithFullMemory, &ExInfo, NULL, NULL);
    //BOOL bOK = pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL);

    if (bOK)
    {
     retval = EXCEPTION_EXECUTE_HANDLER;
    }
    ::CloseHandle(hFile);
   }
  }
  ::FreeLibrary(hDll);
 } 

 return retval;
}

 

프로그램 시작 시 아래 추가

 

SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)TopExceptionFilter);