封裝了一個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文件的代碼就被強制鏈接進來了。
此外,如果是服務類型的程序,還可以在異常處理函數中增加自動啟動新實例的功能,以保證服務不間斷。