概述:
- 注冊生成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文件,可自動定位代碼。