程序崩潰時自動記錄minidump的c++類


封裝了一個C++類,當程序意外崩潰的時候可以生成dump文件,以便確定錯誤原因。

頭文件:

 1 //crash_dumper_w32.h
 2 
 3 #ifndef _CRASH_DUMPER_H_
 4 
 5 #define _CRASH_DUMPER_H_
 6 
 7 
 8 #include <windows.h>
 9 
10 class CrashDumper
11 
12 {
13 
14 public:
15 
16        CrashDumper();
17 
18        ~CrashDumper();
19 
20        static bool _PlaceHolder();
21 
22 private:
23 
24        LPTOP_LEVEL_EXCEPTION_FILTER m_OriginalFilter;
25 
26        static LONG WINAPI ExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo);
27 
28 };
29 
30 
31 namespace
32 
33 {
34        const bool bPlaceHolder = CrashDumper::_PlaceHolder();
35 
36 }
37 
38 #endif

實現文件:

 

  1 crash_dumper_w32.cpp
  2 
  3  
  4 
  5 #include <windows.h>
  6 
  7 #include <tchar.h>
  8 
  9 #include <dbghelp.h>
 10 
 11 #include <string>
 12 
 13  
 14 
 15 #include "crash_dumper_w32.h"
 16 
 17  
 18 
 19 #ifdef UNICODE    
 20 
 21 #     define tstring wstring     
 22 
 23 #else       
 24 
 25 #     define tstring string 
 26 
 27 #endif
 28 
 29  
 30 
 31 #pragma comment(lib, "dbghelp.lib")
 32 
 33  
 34 
 35 CrashDumper dumper;
 36 
 37  
 38 
 39 CrashDumper::CrashDumper()
 40 
 41 {
 42 
 43        m_OriginalFilter = SetUnhandledExceptionFilter(ExceptionFilter);
 44 
 45 }
 46 
 47  
 48 
 49 CrashDumper::~CrashDumper()
 50 
 51 {
 52 
 53        SetUnhandledExceptionFilter(m_OriginalFilter);
 54 
 55 }
 56 
 57  
 58 
 59 LONG WINAPI CrashDumper::ExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
 60 
 61 {
 62 
 63        bool bDumpOK = false;
 64 
 65        DWORD dwProcess = GetCurrentProcessId();
 66 
 67        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcess);
 68 
 69        if (hProcess != INVALID_HANDLE_VALUE)
 70 
 71        {
 72 
 73               TCHAR szPath[MAX_PATH];
 74 
 75               if (GetModuleFileName(NULL, szPath, sizeof(szPath)))
 76 
 77               {
 78 
 79                      std::tstring strDumpFileName = szPath;
 80 
 81                      strDumpFileName += TEXT(".dmp");
 82 
 83                      HANDLE hFile = CreateFile(strDumpFileName.c_str(), FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, NULL, NULL);
 84 
 85                      if (hFile != INVALID_HANDLE_VALUE)
 86 
 87                      {
 88 
 89                             MINIDUMP_EXCEPTION_INFORMATION exception_information;
 90 
 91                             exception_information.ThreadId = GetCurrentThreadId();
 92 
 93                             exception_information.ExceptionPointers = ExceptionInfo;
 94 
 95                             exception_information.ClientPointers = TRUE;
 96 
 97                             if (MiniDumpWriteDump(hProcess, dwProcess, hFile, MiniDumpNormal, &exception_information, NULL, NULL))
 98 
 99                             {
100 
101                                    bDumpOK = true;
102 
103                             }
104 
105  
106 
107                             CloseHandle(hFile);
108 
109                      }
110 
111               }
112 
113  
114 
115               CloseHandle(hProcess);
116 
117        }
118 
119  
120 
121        if (bDumpOK)
122 
123               MessageBox(NULL, TEXT("本程序遇到未處理的異常,MiniDump文件已經生成在程序的運行目錄。"), TEXT("提示"), MB_OK);
124 
125        else
126 
127               MessageBox(NULL, TEXT("本程序遇到未處理的異常,生成MiniDump文件失敗。"), TEXT("提示"), MB_OK);
128 
129  
130 
131        return EXCEPTION_EXECUTE_HANDLER;
132 
133 }
134  
135 
136 bool CrashDumper::_PlaceHolder() {return true;}

代碼很簡單,唯一需要提一下的是下面的一句代碼,這個技巧是為了解決當crash_dumper_w32.cpp文件被編譯成單獨的靜態庫在程序中使用不起作用的問題。

 

namespace

{

       const bool bPlaceHolder = CrashDumper::_PlaceHolder();

}

 

之所以在靜態庫中.cpp中的代碼不起作用,是因為沒有代碼去調用crash_dumper_w32.cpp的代碼,鏈接的時候就被編譯器給丟掉了。上面的語句在匿名空間中定義了一個變量,這樣,每一個包含它的.cpp文件就“被迫”創建了一個不可訪問的bPlaceHolder變量,而該變量又必須使用CrashDumper::_PlaceHolder()函數來初始化。crash_dumper_w32.cpp文件的代碼就被強制鏈接進來了。

 

此外,如果是服務類型的程序,還可以在異常處理函數中增加自動啟動新實例的功能,以保證服務不間斷。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM