前言:通过drwtsn32、NTSD、CDB等调试工具生成Dump文件,drwtsn32存在的缺点虽然NTSD、CDB可以完全解决,但并不是所有的操作系统中都安装了NTSD、CDB等调试工具。了解了mini dump文件格式后,完全可以程序自动生成Dump文件。
本文主要讨论以下内容:
1、运行原理
2、程序修改
3、注意事项
一、运行原理
当程序遇到未处理异常(主要指非指针造成)导致程序崩溃死,如果在异常发生之前调用了SetUnhandledExceptionFilter()函数,异常交给函数处理。MSDN中描述为:
Issuing SetUnhandledExceptionFilter replaces the existing top-level exception filter for all existing and all future threads in the calling process.
因而,在程序开始处增加SetUnhandledExceptionFilter()函数,并在函数中利用适当的方法生成Dump文件,即可实现需要的功能。
二、程序修改
1、重载<< 操作符。(本步可以不实现)
std::ostream&operator<
{
returnos <
<
<
<
<
}
2、实现UnhandledExceptionFilter
#include"minidmp.h"
LONG WINAPI GPTUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
{
CreateMiniDump(pExceptionInfo, L"Exception.dmp");
std::cerr <ExceptionRecord) << std::endl;
exit(pExceptionInfo->ExceptionRecord->ExceptionCode);
returnEXCEPTION_EXECUTE_HANDLER;//程序停止运行
}
3、在异常发生之前调用SetUnhandledExceptionFilter(GPTUnhandledExceptionFilter);
通常在Main()函数开始时调用即可。
4、CreateMiniDump()函数在minidmp.h头文件中定义,文件如下:
#pragmaonce
#include
#include
#include
#pragmacomment(lib,"dbghelp.lib")
inlineBOOL IsDataSectionNeeded(constWCHAR* pModuleName)
{
if(pModuleName == 0)
{
returnFALSE;
}
WCHAR szFileName[_MAX_FNAME] = L"";
_wsplitpath(pModuleName, NULL, NULL, szFileName, NULL);
if(wcsicmp(szFileName, L"ntdll") == 0)
returnTRUE;
returnFALSE;
}
inlineBOOL CALLBACK MiniDumpCallback(PVOIDpParam,
constPMINIDUMP_CALLBACK_INPUTpInput,
PMINIDUMP_CALLBACK_OUTPUTpOutput)
{
if(pInput == 0 || pOutput == 0)
returnFALSE;
switch(pInput->CallbackType)
{
caseModuleCallback:
if(pOutput->ModuleWriteFlags & ModuleWriteDataSeg)
if(!IsDataSectionNeeded(pInput->Module.FullPath))
pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg);
caseIncludeModuleCallback:
caseIncludeThreadCallback:
caseThreadCallback:
caseThreadExCallback:
returnTRUE;
default:;
}
returnFALSE;
}
inlinevoidCreateMiniDump(EXCEPTION_POINTERS* pep, LPCTSTR strFileName)
{
HANDLE hFile = CreateFile(strFileName, GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if((hFile != NULL) && (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= 0;
MINIDUMP_TYPE mdt= (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory |
MiniDumpWithDataSegs |
MiniDumpWithHandleData |
0x00000800/*MiniDumpWithFullMemoryInfo*/|
0x00001000/*MiniDumpWithThreadInfo*/|
MiniDumpWithUnloadedModules);
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
hFile, mdt, (pep != 0) ? &mdei : 0, 0, &mci);
CloseHandle(hFile);
}
}
三、注意事项
1、可执行文件(exe)必须找到dbghelp.dll,才能生成Dump文件。这个DLL可以从调试工具包中找到。
2、当异常代码定位成功以后,如果无法阻止异常的产生,可以用__try 结构包装异常代码,__try 和try 不同,前者可以捕获非法指针产生的异常。
__try {
// 会异常的函数
}
__except( EXCEPTION_EXECUTE_HANDLER ){
// 异常处理
}
参考文档: