VS2010下使用dmp檔案和pdb檔案定位程式異常程式碼行號的注意事項
阿新 • • 發佈:2019-01-23
2018-01-12 建立人:Ruo_Xiao
2018-01-15 修改人:Ruo_Xiao
新增為dump、exe和pdb版本保持一致的原因。
一、minidump檔案
- 崩潰轉儲是建立一個應用程式崩潰瞬間的狀態映象。
- 初代的轉儲檔案是記錄了程序的虛擬空間中全部內容,但是這樣的檔案非常大,而且對於不太熟練使用的人員來說冗餘資訊太多。
- xp之後,MicroSoft發明了“minidump”的轉儲技術,即:小型的,只是包含了必要的執行緒呼叫堆疊等資訊檔案。該檔案很小,很容易通過網路傳送,同時也可以定製該檔案記錄的資訊,非常的靈活。
- 生成minidump的函式包含在DbgHelp.dll中。
二、pdb檔案
後續加入!
三、注意事項
1、 exe檔案、dmp檔案和pdb檔案必須保持一致!
在上篇部落格中,我們簡單的介紹瞭如何用dmp檔案和pdb檔案定位程式碼中崩潰位置。連結如下:
http://blog.csdn.net/itworld123/article/details/79041500
上述能夠成功定位的一個前提是exe檔案、dmp檔案和pdb檔案都是同時生成的,即:exe檔案和pdb檔案同時生成,dmp檔案是由當前exe生成的。若生成崩潰資訊之後,又重新編譯了exe,與此同時也重新生成了pdb檔案,那麼即使程式碼沒有任何改動,此時WinDbg也沒有辦法進行程式碼行號定位了,顯示的資訊如下:
WRITE_ADDRESS: 0000000c FOLLOWUP_IP: TEST11+100b 012b100b c7050c00000005000000 mov dword ptr ds:[0Ch],5 MOD_LIST: <ANALYSIS/> FAULTING_THREAD: 0000139c BUGCHECK_STR: APPLICATION_FAULT_NULL_CLASS_PTR_DEREFERENCE_INVALID_POINTER_WRITE_WRONG_SYMBOLS PRIMARY_PROBLEM_CLASS: NULL_CLASS_PTR_DEREFERENCE DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE LAST_CONTROL_TRANSFER: from 746b336a to 012b100b STACK_TEXT: WARNING: Stack unwind information not available. Following frames may be wrong. 0029f934 746b336a 7efde000 0029f980 77139902 TEST11+0x100b 0029f940 77139902 7efde000 7735f926 00000000 kernel32!BaseThreadInitThunk+0x12 0029f980 771398d5 012b132d 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x63 0029f998 00000000 012b132d 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x36 STACK_COMMAND: ~0s; .ecxr ; kb SYMBOL_STACK_INDEX: 0 SYMBOL_NAME: TEST11+100b FOLLOWUP_NAME: MachineOwner IMAGE_NAME: TEST11.exe BUCKET_ID: WRONG_SYMBOLS FAILURE_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE_c0000005_TEST11.exe!Unknown WATSON_STAGEONE_URL: http://watson.microsoft.com/StageOne/TEST11_exe/0_0_0_0/5a58a12a/TEST11_exe/0_0_0_0/5a58a12a/c0000005/0000100b.htm?Retriage=1 Followup: MachineOwner
上述資訊大家可以看到,定位原始碼的功能已經消失了。
2、關閉程式碼優化功能。
#include "stdafx.h" #include <windows.h> #include <DbgHelp.h> #pragma comment(lib,"Dbghelp.lib") static long __stdcall CrashInfocallback(_EXCEPTION_POINTERS *pexcp); void ErrorFun(int *p) { p[2] = 10; //這裡崩潰 } int _tmain(int argc, _TCHAR* argv[]) { ::SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)CrashInfocallback); int *pi = NULL; ErrorFun(pi); return 0; } long __stdcall CrashInfocallback( _EXCEPTION_POINTERS *pexcp) { HANDLE hDumpFile = ::CreateFile( L"MEMORY.DMP", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if( hDumpFile != INVALID_HANDLE_VALUE) { MINIDUMP_EXCEPTION_INFORMATION dumpInfo; dumpInfo.ExceptionPointers = pexcp; dumpInfo.ThreadId = ::GetCurrentThreadId(); dumpInfo.ClientPointers = TRUE; ::MiniDumpWriteDump( ::GetCurrentProcess(), ::GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL ); } ::CloseHandle(hDumpFile); return 0; }
上述程式碼在沒有關閉程式碼優化功能的情況下,按照上篇部落格的方法,生成的資訊如下:
WRITE_ADDRESS: 00000008
FOLLOWUP_IP:
TEST11!wmain+b [d:\huawei\projects\test11\test11\test11.cpp @ 22]
013e100b c705080000000a000000 mov dword ptr ds:[8],0Ah
MOD_LIST: <ANALYSIS/>
FAULTING_THREAD: 00000814
BUGCHECK_STR: APPLICATION_FAULT_NULL_CLASS_PTR_DEREFERENCE_INVALID_POINTER_WRITE_WRONG_SYMBOLS
PRIMARY_PROBLEM_CLASS: NULL_CLASS_PTR_DEREFERENCE
DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE
LAST_CONTROL_TRANSFER: from 013e120c to 013e100b
STACK_TEXT:
0038f9cc 013e120c 00000001 00032888 00033a40 TEST11!wmain+0xb [d:\huawei\projects\test11\test11\test11.cpp @ 22]
0038fa10 746b336a 7efde000 0038fa5c 77139902 TEST11!__tmainCRTStartup+0x122 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 552]
WARNING: Stack unwind information not available. Following frames may be wrong.
0038fa1c 77139902 7efde000 775e96bf 00000000 kernel32!BaseThreadInitThunk+0x12
0038fa5c 771398d5 013e132d 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x63
0038fa74 00000000 013e132d 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x36
STACK_COMMAND: ~0s; .ecxr ; kb
FAULTING_SOURCE_CODE:
18: int _tmain(int argc, _TCHAR* argv[])
19: {
20: ::SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)CrashInfocallback);
21: int *pi = NULL;
> 22: ErrorFun(pi);
23: return 0;
24: }
25:
26: long __stdcall CrashInfocallback( _EXCEPTION_POINTERS *pexcp)
27: {
SYMBOL_STACK_INDEX: 0
SYMBOL_NAME: test11!wmain+b
FOLLOWUP_NAME: MachineOwner
IMAGE_NAME: TEST11.exe
BUCKET_ID: WRONG_SYMBOLS
FAILURE_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE_c0000005_TEST11.exe!wmain
WATSON_STAGEONE_URL: http://watson.microsoft.com/StageOne/TEST11_exe/0_0_0_0/5a58a3c4/TEST11_exe/0_0_0_0/5a58a3c4/c0000005/0000100b.htm?Retriage=1
Followup: MachineOwner
大家可以發現,WinDbg確實定位到了原始碼位置,但是僅僅是函式外面,沒有進去。
後來上網查了很多資料,最後隱約感覺到可能是Release程式碼優化的原因,所以當我關閉程式碼優化的時候,成功地定位到了真正的位置。資訊如下:
WRITE_ADDRESS: 00000008
FOLLOWUP_IP:
TEST11!ErrorFun+6 [d:\huawei\projects\test11\test11\test11.cpp @ 15]
00df1006 c740080a000000 mov dword ptr [eax+8],0Ah
MOD_LIST: <ANALYSIS/>
FAULTING_THREAD: 000013ac
BUGCHECK_STR: APPLICATION_FAULT_NULL_CLASS_PTR_DEREFERENCE_INVALID_POINTER_WRITE_WRONG_SYMBOLS
PRIMARY_PROBLEM_CLASS: NULL_CLASS_PTR_DEREFERENCE
DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE
LAST_CONTROL_TRANSFER: from 00df102f to 00df1006
STACK_TEXT:
0028fbfc 00df102f 00000000 00000000 0028fc50 TEST11!ErrorFun+0x6 [d:\huawei\projects\test11\test11\test11.cpp @ 15]
0028fc0c 00df1232 00000001 003b2888 003b3a40 TEST11!wmain+0x1f [d:\huawei\projects\test11\test11\test11.cpp @ 22]
0028fc50 746b336a 7efde000 0028fc9c 77139902 TEST11!__tmainCRTStartup+0x122 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 552]
WARNING: Stack unwind information not available. Following frames may be wrong.
0028fc5c 77139902 7efde000 77413872 00000000 kernel32!BaseThreadInitThunk+0x12
0028fc9c 771398d5 00df1353 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x63
0028fcb4 00000000 00df1353 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x36
STACK_COMMAND: ~0s; .ecxr ; kb
FAULTING_SOURCE_CODE:
11: static long __stdcall CrashInfocallback(_EXCEPTION_POINTERS *pexcp);
12:
13: void ErrorFun(int *p)
14: {
> 15: p[2] = 10; //?a¨¤?¡À¨¤¨¤¡ê
16: }
17:
18: int _tmain(int argc, _TCHAR* argv[])
19: {
20: ::SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)CrashInfocallback);
SYMBOL_STACK_INDEX: 0
SYMBOL_NAME: test11!ErrorFun+6
FOLLOWUP_NAME: MachineOwner
IMAGE_NAME: TEST11.exe
BUCKET_ID: WRONG_SYMBOLS
FAILURE_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE_c0000005_TEST11.exe!ErrorFun
WATSON_STAGEONE_URL: http://watson.microsoft.com/StageOne/TEST11_exe/0_0_0_0/5a58a4b0/TEST11_exe/0_0_0_0/5a58a4b0/c0000005/00001006.htm?Retriage=1
Followup: MachineOwner
拓展:VS2010關閉程式碼優化的方法:
專案 -> 工程名 + 屬性
彈出如下圖所示的框:
對“優化”選擇“已禁用”,預設為“使速度最大化”,確定之後,重新編譯程式即可。
四、總結
- 禁用程式優化功能。
- exe、pdb和dmp檔案保持一致。
解釋:exe檔案和pdb檔案同時生成,dmp檔案是由當前exe生成的。