讓程序在崩潰時體面的退出之Dump文件

         在我的那篇《讓程序在崩潰時體面的退出之CallStack》中提供了一個在程序崩潰時得到CallStack的方法。可是要想得到CallStack,必須有pdb文件的支持。但是一般情況下,發佈出去的程序都是Release版本的,都不會附帶pdb文件。那麼我們怎麼能在程序崩潰的時候找到出錯的具體位置呢?這個時候就該Dump文件出場了!Dump文件是進程的內存鏡像,可以把程序運行時的狀態完整的保存下來。
        要想在程序崩潰的時候創建Dump文件,就需要用到DbgHelp.dll中Windows API的MiniDumpWriteDump()函數。該函數聲明如下:
BOOL WINAPI MiniDumpWriteDump(
  __in  HANDLE hProcess,
  __in  DWORD ProcessId,
  __in  HANDLE hFile,
  __in  MINIDUMP_TYPE DumpType,
  __in  PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
  __in  PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
  __in  PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);

        具體的參數和返回值的解釋可以查找MSDN,有很詳細的說明。下面依然用上一篇文章中的例子代碼來說明怎麼在程序崩潰的時候創建Dump文件。

// 處理Unhandled Exception的回調函數
//
LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException)
{	
	// 這裏彈出一個錯誤對話框並退出程序
	//
	FatalAppExit(-1,  _T("*** Unhandled Exception! ***"));

	return EXCEPTION_EXECUTE_HANDLER;
}

// 一個有函數調用的類
// 
class CrashTest
{
public:
	void Test() 
	{ 
		Crash(); 
	}

private:
	void Crash() 
	{ 
		// 除零,人爲的使程序崩潰
		//
		int i = 13;
		int j = 0;
		int m = i / j;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	// 設置處理Unhandled Exception的回調函數
	// 
	SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler); 

	CrashTest test;
	test.Test();

	return 0;
}

        在上面的程序崩潰的時候,會調用函數ApplicationCrashHandler()。創建Dump文件的代碼就需要添加到該函數中。下面就是一個創建Dump文件的函數。

// 創建Dump文件
// 
void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)
{
	// 創建Dump文件
	//
	HANDLE hDumpFile = CreateFile(lpstrDumpFilePathName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	// Dump信息
	//
	MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
	dumpInfo.ExceptionPointers = pException;
	dumpInfo.ThreadId = GetCurrentThreadId();
	dumpInfo.ClientPointers = TRUE;

	// 寫入Dump文件內容
	//
	MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

	CloseHandle(hDumpFile);
}

        在函數ApplicationCrashHandler()用類似下面的代碼來調用上面的函數,就可以在程序崩潰的時候創建Dump文件。

CreateDumpFile(_T("C:\\Test.dmp"), pException);

        下面簡單說一下Dump文件的用法。將Dump文件拷貝到含有應用程序和對應的pdb文件的目錄,在VS裏面打開Dump文件(或者直接雙擊Dump文件),VS會自動創建一個Solution,直接調試運行,代碼就會停到使程序崩潰的那一行上。就跟在VS裏面調試代碼一摸一樣。(VS2008)


        在VS2010裏打開Dump文件,會顯示一個Minidump File Summary,並且可以進行下面圖中的操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章