미니 덤프
프로그램이 Unhandled Exception으로 종료될때 원인 분석을 위해 덤프 파일을 생성 하는 방법입니다.
 
DEBUG 모드로 컴파일된 실행파일(.exe) 실행시 덤프파일이 생성됩니다.
분석을 위해서 컴파일 당시에 생성된 .pdb 파일이 동일 폴더에 있어야 합니다.
 
컴파일 당시 소스가 원래 위치에 그대로 있어야 한다.
(소스 위치를 지정해주면 되긴 하지만 소스 내용이 바뀐거면 안됩니다..)
 
 
덤프 생성 샘플
#include <iostream>
#include <windows.h>
#include <tchar.h>

using namespace std;

#include <DbgHelp.h>

//에러 메시지 출력용 함수
VOID printLastError(DWORD error = GetLastError())
{
	TCHAR* lpOSMsg;
	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		error,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(LPTSTR)&lpOSMsg,
		0,
		NULL);
	_tprintf(_T("[ERROR] [%d] %s\n"), error, lpOSMsg);
	LocalFree(lpOSMsg);
}


LPTOP_LEVEL_EXCEPTION_FILTER PreviousExceptionFilter = NULL;

//Unhandled Exception 발생시 호출 될 CallBack 함수 원형
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
	);

//Unhandled Exception 발생시 호출될 콜백 함수
LONG WINAPI UnHandledExceptionFilter(struct _EXCEPTOIN_POINTERS* exceptionInfo)
{
	//반드시 로딩
	HMODULE DllHandle = LoadLibrary(_T("DBGHELP.DLL"));
	if (DllHandle == NULL)
	{
		printLastError();
		return EXCEPTION_CONTINUE_SEARCH;
	}

	//DBGHELP.DLL에서 MiniDumpWriteDump를 불러와 Dump라고 정의하며 이걸로 덤프 파일을 생성합니다.
	MINIDUMPWRITEDUMP Dump = (MINIDUMPWRITEDUMP)GetProcAddress(DllHandle, "MiniDumpWriteDump");
	if (Dump == NULL)
	{
		printLastError();
		return EXCEPTION_CONTINUE_SEARCH;
	}


	SYSTEMTIME SystemTime;
	GetLocalTime(&SystemTime); //현재시간 획득

	TCHAR DumpPath[MAX_PATH] = { 0, };
	//덤프 파일 이름 설정
	_sntprintf_s(DumpPath, MAX_PATH, _TRUNCATE, _T("%d-%d-%d %d_%d_%d.dmp"),
		SystemTime.wYear,
		SystemTime.wMonth,
		SystemTime.wDay,
		SystemTime.wHour,
		SystemTime.wMinute,
		SystemTime.wSecond);

	//덤프 파일 생성
	HANDLE FileHandle = CreateFile(DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (FileHandle == INVALID_HANDLE_VALUE)
	{
		printLastError();
		return EXCEPTION_CONTINUE_SEARCH;
	}

	//MiniDump 예외 정보 저장 구조체
	_MINIDUMP_EXCEPTION_INFORMATION MiniDumpExceptionInfo;
	MiniDumpExceptionInfo.ThreadId = GetCurrentThreadId();
	MiniDumpExceptionInfo.ExceptionPointers = (PEXCEPTION_POINTERS)exceptionInfo;
	MiniDumpExceptionInfo.ClientPointers = NULL;

	//현재 프로세스에 대한 덤프 기록을 실행합니다.
	BOOL Success = Dump(
		GetCurrentProcess(),
		GetCurrentProcessId(),
		FileHandle,    //덤프를 기록할 파일 핸들
		MiniDumpNormal,
		&MiniDumpExceptionInfo, //MiniDump 예외 정보
		NULL,
		NULL);

	//덤프 기록 설공시 수행
	if (Success)
	{
		CloseHandle(FileHandle);
		return EXCEPTION_EXECUTE_HANDLER;
	}
	CloseHandle(FileHandle);

	return EXCEPTION_CONTINUE_SEARCH;
}

//UnHandled Exception 발생시 덤프를 만들기 위해 사용자 정의한 UnHandledExceptionFilter()가 호출되도록 설정
//프로그램 시작 부분에서 호출하도록 합니다.
BOOL BeginDump(VOID)
{
	//잘못된 연산 메시지 창이 나오지 않도록 설정
	SetErrorMode(SEM_FAILCRITICALERRORS);

	//Unhandled Exception 발생시 호출될 CallBack 함수 등록
	//PreviousExceptionFilter는 원래 설정을 담아 프로그램 종료시 복구 용도로 쓰입니다.
	PreviousExceptionFilter = SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)UnHandledExceptionFilter);

	return TRUE;
}

//원래 설정으로 복구하여 덤프가 종료되도록 합니다.
//프로그램 종료 부분에서 호출하도록 합니다.
BOOL EndDump(VOID)
{
	//프로그램 종료 전에 원래 설정으로 복구
	SetUnhandledExceptionFilter(PreviousExceptionFilter);
	return TRUE;
}


class CTestCls {
public:
	BOOL isOpened;
};

int main()
{
	setlocale(LC_ALL, ""); //한글 출력 설정

	BeginDump();

	CTestCls* testCls = new CTestCls();
	testCls = NULL;
	testCls->isOpened = FALSE; //Unhandled Exception

	EndDump();
	return 0;
}​


덤프 파일 분석 방법
0. 덤프 파일이 생기면
1. 덤프파일을 Visual Studio로 연다.
2. F5 로 디버그를 시작하면 덤프 파일 솔루션을 저장하라고 나옵니다.
3. 덤프 파일 솔루션을 저장하면 덤프가 발생한 지점의 소스가 표시됩니다.
 
**. 주의 : 실행 파일을 만들때 생성된 PDB 파일과 같이 두어야 분석 가능합니다.
 
 

'C++' 카테고리의 다른 글

[MFC] CTreeView에 바탕화면 폴더 트리 생성 예제  (0) 2010.12.03
[MFC] 인터넷 HTML 소스 다운로드  (1) 2010.12.01
윈도우 서비스 (service)  (0) 2010.11.25
performance counter (성능 모니터링)  (0) 2010.11.25
Memory Pool (메모리 풀)  (1) 2010.11.13
virtual 와 상속 속성  (0) 2010.11.10
stable priority queue  (0) 2010.11.08
log4cxx  (0) 2010.11.06