概述:
- 注冊生成dump文件的函數。
- 當程序收到沒有捕獲的異常時,調用上述函數,生成dump文件。
- 利用Windbg結合編譯程序時生成的pdb和代碼來分析dump文件,定位問題。
如下代碼生成dump文件(轉):
#include <Windows.h> #include <stdio.h> #include <DbgHelp.h> #pragma comment(lib, "dbghelp.lib") inline BOOL IsDataSectionNeeded(const WCHAR* pModuleName) { if(pModuleName == NULL) { return FALSE; } WCHAR szFileName[_MAX_FNAME] = L""; _wsplitpath(pModuleName, NULL, NULL, szFileName, NULL); if(wcsicmp(szFileName, L"ntdll") == 0) return TRUE; return FALSE; } inline BOOL CALLBACK MiniDumpCallback(PVOID pParam, const PMINIDUMP_CALLBACK_INPUT pInput, PMINIDUMP_CALLBACK_OUTPUT pOutput) { if(pInput == 0 || pOutput == 0) return FALSE; switch(pInput->CallbackType) { case ModuleCallback: if(pOutput->ModuleWriteFlags & ModuleWriteDataSeg) if(!IsDataSectionNeeded(pInput->Module.FullPath)) pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg); case IncludeModuleCallback: case IncludeThreadCallback: case ThreadCallback: case ThreadExCallback: return TRUE; default:; } return FALSE; } inline void CreateMiniDump(PEXCEPTION_POINTERS pep, LPCTSTR strFileName) { HANDLE hFile = CreateFile(strFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile != INVALID_HANDLE_VALUE) { MINIDUMP_EXCEPTION_INFORMATION mdei; mdei.ThreadId = GetCurrentThreadId(); mdei.ExceptionPointers = pep; mdei.ClientPointers = FALSE; MINIDUMP_CALLBACK_INFORMATION mci; mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback; mci.CallbackParam = NULL; ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), hFile, MiniDumpNormal, (pep != NULL) ? &mdei : NULL, NULL, &mci); CloseHandle(hFile); } } LONG __stdcall MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo) { CreateMiniDump(pExceptionInfo, "core.dmp"); return EXCEPTION_EXECUTE_HANDLER; }
確保程序開始執行如下代碼,然后程序崩潰時會調用上面代碼創建dump文件:
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
分析生成的dump文件需要如下:
- 編譯程序時生成的PDB,如果是release版本:
- 需要禁用優化 - VS - Project Property - C/C++ Optimization - Release - Optimization - Disabled
- 啟用生成調試信息 - VS - Project Property - Linker - Debugging - Generate Debug Info - Yes.
- 代碼
分析dump文件步驟如下:
- 運行Windbg。
- 指定PDB文件路徑: File - Symbol File Path。多個路徑用分號分隔。
- 指定代碼路徑:File - Source File Path
- 載入dump文件。
- Windbg命令行輸入: !analyze -v
- 等待結果 - 函數調用堆棧,程序崩潰代碼。busy狀態表示正在生成結果。
注釋:
- 沒有代碼,只有PDB,也可以顯示函數調用堆棧,但是不會定位到具體代碼。
- Windbg中,配置 Symbol File Path: srv*c:\symbols*http://msdl.microsoft.com/download/symbols,可以解決本地找不到symbol問題。定位一般問題,不是必須。c:\symbols為本地緩存PDB目錄。只會同步用到的symbol。
- Windbg的附帶工具symchk可以用來下載指定dll的pdb文件:
- 下載特定dll的pdb文件:symchk /r c:\windows\system32\secur32.dll /s SRV*c:\symbols\*http://msdl.microsoft.com/download/symbols
- 下載特定目錄下的dll的pdb文件:symchk /r c:\windows\system32 /s SRV*c:\symbols\*http://msdl.microsoft.com/download/symbols
- 如果dump文件被拷貝到編譯程序的機器上,無需指定代碼路徑,只需指定pdb文件,可自動定位代碼。