[c++] Windows下dump檔案生成與分析
一、 生成Dump檔案方式
1.1工作管理員
在程式崩潰後,先不關閉程式,在工作管理員中找到該程式對應的程序。右鍵—>建立轉儲檔案。
此時會在預設的目錄下創建出一個dump檔案。
可以看出,此種方法只適用於程式崩潰但沒有立即自行退出的情況。倘若程式故障後自行退出,則此方法就難以應用。不過,我們可以在登錄檔中新增如下資訊已確保系統在程式崩潰後自行儲存一個dump檔案:
在登錄檔中找到
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\WindowsError Reporting\LocalDumps
新增項如下圖:
其中DumpType代表的含義是:
0 = Create a custom dump
1 = Mini dump
2 = Full dump
如此一來,一旦程式崩潰,系統會在C:\CrashDump下生成一個dump檔案。
1.2WinDbg抓取
程式執行崩潰後,先不關閉程式,將WinDbg附加到改程序上。
執行命令:.dump –ma Test.dmp ,則會產生一個Test.dmp的轉儲檔案。
1.3程式中加入儲存Dump的程式碼
通過SetUnhandledExceptionFilter設定捕獲dump的入口,然後通過MiniDumpWriteDump生成dump檔案。
如下程式在程式異常時會自行轉儲一個名為Test.dmp的dump檔案。
[cpp] view plain copy
- #include<Windows.h>
- #include<DbgHelp.h>
- #pragma comment(lib,"DbgHelp.lib")
- // 建立Dump檔案
- void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)
- {
- 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);
- }
- // 處理Unhandled Exception的回撥函式
- LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException)
- {
- CreateDumpFile(L"Test.dmp",pException);
- return EXCEPTION_EXECUTE_HANDLER;
- }
- void fun(int *p)
- {
- p[0]=0;
- }
- int main(int argc, char * argv[])
- {
- //註冊異常處理函式
- SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
- fun(NULL);
- return 0;
- }
二、除錯Dump檔案
2.1.VS除錯
用VS開啟dmp檔案。測試時 dmp檔案時本地產生的,因此VS會依據dmp檔案自行找到exe,pdb和原始碼的路徑。因此直接點選除錯,程式會出錯程式碼行中斷。
但若dmp檔案是exe在另一臺機器上產生的,則我們最好把exe,pdb,dmp放到同一資料夾下,必須保證pdb與出問題的exe是同一時間生成的,用VS開啟dmp檔案後還需要設定符號表檔案路徑和原始碼路徑:
(1) 當把pdb檔案與dmp檔案放入同一目錄下時,就不需設定其路徑,否則需要設定
工具->選項->除錯->符號:
(2)還需設定原始碼路徑:
屬性->除錯原始碼:
這樣點選“使用僅限本機進行除錯”,即可在出錯程式碼行中斷:
2.2 WinDbg除錯
(1)設定pdb路徑:File ->Symbol File Path
(2)設定exe路徑:File -> Image File Path
(3)設定原始碼路徑:File -> Source File Path(指sln所在目錄)
(4)開啟dmp檔案:File ->Open Crash Dump
(5)執行命令 !analyze –v
由分析結果可以看出,在main.cpp第7行出錯,錯誤型別:NULL_POINTER_WRITE.