項目地址:https://code.google.com/p/google-breakpad/ 訪問不了請掛VPN
這是一個由google主導的開源項目,官方介紹為:An open-source multi-platform crash reporting system,即 開源的多平台崩潰上報系統。
這是由google員工在工作中那20%的自由創造時間創造的作品,真正對技術熱愛的人才會在自由時間改變世界,只完成工作的人永遠只能做一把被人用完就丟的槍。
言歸正傳,google breakpad 支持iOS linux windows,
linux的崩潰捕獲機制我比較熟悉,做好信號處理已經能搞定一大半了;
但是我對windows的崩潰捕獲機制僅限於SEH,SEH無法滿足所有場景的崩潰捕獲(當然google breakpad也不能滿足所有場景),
所以本文主要描述在windows平台上如何使用google breakpad捕獲崩潰。
源碼下載:
使用svn下載即可,不會可以點右上角的紅X。
源碼結構:主要在src的目錄下
build: 編譯腳本
client:主要包括捕獲以及dump代碼
common:通用支持代碼
google_breakpad:breakpad使用的公共支持代碼
processor:崩潰處理核心代碼
testing:測試代碼
third_party:第三方支持庫
tools:一些小工具,用於處理dump文件和符號表
支持的捕獲方式:
在exception_handler.h文件中可以看到以下定義:
enum HandlerType { HANDLER_NONE = 0, HANDLER_EXCEPTION = 1 << 0, // SetUnhandledExceptionFilter HANDLER_INVALID_PARAMETER = 1 << 1, // _set_invalid_parameter_handler HANDLER_PURECALL = 1 << 2, // _set_purecall_handler HANDLER_ALL = HANDLER_EXCEPTION | HANDLER_INVALID_PARAMETER | HANDLER_PURECALL };
也就是有這3種捕獲方式:
1.HANDLER_EXCEPTION - 即使用 SetUnhandledExceptionFilter 函數捕獲,也就是大家熟知的SEH
2.HANDLER_INVALID_PARAMETER - 使用 _set_purecall_handler 捕獲純虛函數導致的崩潰
3.HANDLER_PURECALL - 使用 _set_invalid_parameter_handler 捕獲錯誤參數調用導致的崩潰
google breakpad 是一套系統,支持dump文件的上傳,上傳是通過crash_report_sender完成的,協議使用http,Lib使用wininet,本文只做比較基礎的本地dump用法演示,
整套c/s架構演示待我有時間后添加吧。
google breakpad 支持進程內捕獲、進程外捕獲,各有優劣:
進程外捕獲:
不會被崩潰進程自身影響,dump過程比較不易出現缺失信息、出錯等問題;
但是堆棧溢出有可能抓不到,死鎖處理不了(這也不是崩潰)。
進程內捕獲:
有可能影響到自身的dump過程。
這玩意的選擇自己看着辦吧,我這里主要演示如何進程內捕獲。
如何使用:
先簡單看看代碼調用方法,其實很簡單,就是聲明一個ExceptionHandler對象,ExceptionHandler構造函數如下:
ExceptionHandler(const wstring& dump_path, //dump文件存儲路徑 FilterCallback filter, //在寫minidump之前調用,根據返回值決定是否dump MinidumpCallback callback, //寫入minidump后調用 void* callback_context, //上下文,不需要就NULL int handler_types); //指定需要安裝的handle類型, 一般 ExceptionHandler::HANDLER_ALL 搞定 ExceptionHandler(const wstring& dump_path, FilterCallback filter, MinidumpCallback callback, void* callback_context, int handler_types, MINIDUMP_TYPE dump_type, //MINIDUMP_TYPE類型 const wchar_t* pipe_name, //管道名,用於進程外捕獲時的進程間通信 const CustomClientInfo* custom_info); //客戶端信息 ExceptionHandler(const wstring& dump_path, FilterCallback filter, MinidumpCallback callback, void* callback_context, int handler_types, MINIDUMP_TYPE dump_type, HANDLE pipe_handle, const CustomClientInfo* custom_info); ExceptionHandler(const wstring& dump_path, FilterCallback filter, MinidumpCallback callback, void* callback_context, int handler_types, CrashGenerationClient* crash_generation_client);
在windows平台編譯安裝:
環境:win8 + vs2010
1.下載源文件
2.生成工程:
(1)安裝python2.7,講python2.7的安裝目錄設置到環境變量的path中,cmd中輸入python能調用到python就算成功了
(2)打開一個cmd,進入google_breakpad目錄
(3) set GYP_MSVS_VERSION=2010
src\tools\gyp\gyp.bat --no-circular-check src\client\windows\breakpad_client.gyp
(4)sln文件會生成到src\client\windows目錄
(5)使用sln編譯,lib文件會生成到google_breakpad\src\client\windows\debug or release目錄中
友情提示:項目默認是編譯mt的,可以自己根據需求修改
以下開始真正的調用方法:
//一些需要的頭文件 #include <windows.h> #include <tchar.h> #include "google_breakpad/client/windows/crash_generation/client_info.h" #include "google_breakpad/client/windows/crash_generation/crash_generation_server.h" #include "google_breakpad/client/windows/handler/exception_handler.h" #include "google_breakpad/client/windows/common/ipc_protocol.h" //庫 #pragma comment(lib, "exception_handler.lib") #pragma comment(lib, "common.lib") #pragma comment(lib, "crash_generation_client.lib") #pragma comment(lib, "crash_generation_server.lib") //定義靜態的對象 using namespace google_breakpad; static ExceptionHandler* handler = NULL;
實現dump后處理函數:
bool ShowDumpResults(const wchar_t* dump_path, const wchar_t* minidump_id, void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion, bool succeeded) { //MessageBox(NULL, _T("aa"), _T("bb"), 0); TCHAR* text = new TCHAR[1024]; text[0] = _T('\0'); int result = swprintf_s(text, 1024, TEXT("Dump generation request %s\r\n"), succeeded ? TEXT("succeeded") : TEXT("failed")); if (result == -1) { delete [] text; } return succeeded; }
在_tWinMain中創建對象:
wstring wszDumpSavePath = L"F:\\dumptest\\"; //保存dump文件的路徑,可以動態獲取自身的路徑 handler = new ExceptionHandler(wszDumpSavePath.c_str(), NULL, ShowDumpResults, NULL, ExceptionHandler::HANDLER_ALL);
然后就OK了,在程序中人為制造一些崩潰問題,執行程序后,dmp文件就會保存到你設置的路徑了。
如何查看dmp信息:
將dmp+exe+pdb文件放到同一目錄下,雙擊dmp文件(用vs打開),即可查看dmp信息。