1. 程式人生 > >讓程式在崩潰時體面的退出之Dump檔案

讓程式在崩潰時體面的退出之Dump檔案

在我的那篇《讓程式在崩潰時體面的退出之CallStack》中提供了一個在程式崩潰時得到CallStack的方法。可是要想得到CallStack,必須有pdb檔案的支援。但是一般情況下,釋出出去的程式都是 Release版本的,都不會附帶pdb檔案。那麼我們怎麼能在程式崩潰的時候找到出錯的具體位置呢?這個時候就該Dump檔案出場了!Dump檔案是程序的記憶體映象,可以把程式執行時的狀態完整的儲存下來。
        要想在程式崩潰的時候建立Dump檔案,就需要用到DbgHelp.dll中Windows API的MiniDumpWriteDump()函式。該函式宣告如下:
  1. BOOL WINAPI MiniDumpWriteDump(  
  2.   __in  HANDLE hProcess,  
  3.   __in  DWORD ProcessId,  
  4.   __in  HANDLE hFile,  
  5.   __in  MINIDUMP_TYPE DumpType,  
  6.   __in  PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,  
  7.   __in  PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,  
  8.   __in  PMINIDUMP_CALLBACK_INFORMATION CallbackParam  
  9. );  

        具體的引數和返回值的解釋可以查詢MSDN,有很詳細的說明。下面依然用上一篇文章中的例子程式碼來說明怎麼在程式崩潰的時候建立Dump檔案。

  1. // 處理Unhandled Exception的回撥函式
  2. //
  3. LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException)  
  4. {     
  5.     // 這裡彈出一個錯誤對話方塊並退出程式
  6.     //
  7.     FatalAppExit(-1,  _T("*** Unhandled Exception! ***"));  
  8.     return EXCEPTION_EXECUTE_HANDLER;  
  9. }  
  10. // 一個有函式呼叫的類
  11. // 
  12. class CrashTest  
  13. {  
  14. public:  
  15.     void Test()   
  16.     {   
  17.         Crash();   
  18.     }  
  19. private:  
  20.     void Crash()   
  21.     {   
  22.         // 除零,人為的使程式崩潰
  23.         //
  24.         int i = 13;  
  25.         int j = 0;  
  26.         int m = i / j;  
  27.     }  
  28. };  
  29. int _tmain(int argc, _TCHAR* argv[])  
  30. {  
  31.     // 設定處理Unhandled Exception的回撥函式
  32.     // 
  33.     SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);   
  34.     CrashTest test;  
  35.     test.Test();  
  36.     return 0;  
  37. }  

        在上面的程式崩潰的時候,會呼叫函式ApplicationCrashHandler()。建立Dump檔案的程式碼就需要新增到該函式中。下面就是一個建立Dump檔案的函式。

  1. // 建立Dump檔案
  2. // 
  3. void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)  
  4. {  
  5.     // 建立Dump檔案
  6.     //
  7.     HANDLE hDumpFile = CreateFile(lpstrDumpFilePathName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);  
  8.     // Dump資訊
  9.     //
  10.     MINIDUMP_EXCEPTION_INFORMATION dumpInfo;  
  11.     dumpInfo.ExceptionPointers = pException;  
  12.     dumpInfo.ThreadId = GetCurrentThreadId();  
  13.     dumpInfo.ClientPointers = TRUE;  
  14.     // 寫入Dump檔案內容
  15.     //
  16.     MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);  
  17.     CloseHandle(hDumpFile);  
  18. }  

        在函式ApplicationCrashHandler()用類似下面的程式碼來呼叫上面的函式,就可以在程式崩潰的時候建立Dump檔案。

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

        下面簡單說一下Dump檔案的用法。將Dump檔案拷貝到含有應用程式和對應的pdb檔案的目錄,在VS裡面開啟Dump檔案(或者直接雙擊Dump檔案),VS會自動建立一個Solution,直接除錯執行,程式碼就會停到使程式崩潰的那一行上。就跟在VS裡面除錯程式碼一摸一樣。(VS2008)


        在VS2010裡開啟Dump檔案,會顯示一個Minidump File Summary,並且可以進行下面圖中的操作。