dump文件生成与调试(VS2008)

2023-07-29,,

  总结一下dump文件生成调试的方法:  

  1:用SetUnhandledExceptionFilter捕获未处理的异常,包含头文件<windows.h>。函数原型为:

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(
__in LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
);

  SetUnhandledExceptionFilter返回值为:The SetUnhandledExceptionFilter function returns the address of the previous exception filter established with the function. A NULL return value means that there is no current top-level exception handler.返回回掉函数的地址。

  回掉函数原型为:

 typedef LONG (WINAPI *PTOP_LEVEL_EXCEPTION_FILTER)(
__in struct _EXCEPTION_POINTERS *ExceptionInfo
);
typedef PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER;

  回掉函数须返回以下3种类型:

Value Meaning

EXCEPTION_EXECUTE_HANDLER
0x1

Return from UnhandledExceptionFilter and execute the associated exception handler. This usually results in process termination.捕获到异常,并在异常处结束程序。

EXCEPTION_CONTINUE_EXECUTION
0xffffffff

Return from UnhandledExceptionFilter and continue execution from the point of the exception. Note that the filter function is free to modify the continuation state by modifying the exception information supplied through its LPEXCEPTION_POINTERS parameter.表示错误已经被修复,从异常发生处继续执行。如果在回掉函数内部不对异常进行处理,每次回掉结束又会捕获到异常,将导致无限进入SetUnhandledExceptionFilter函数,死循环。

EXCEPTION_CONTINUE_SEARCH
0x0

Proceed with normal execution of UnhandledExceptionFilter. That means obeying the SetErrorMode flags, or invoking the Application Error pop-up message box.捕获到异常,并调用系统默认异常错误框,结束程序。

  2:在SetUnhandledExceptionFilter的回掉函数中,用MiniDumpWriteDump函数将异常写入dump文件。需要包含DbgHelp.h,引入#pragma comment(lib, "dbghelp.lib")。MiniDumpWriteDump函数的原型为:

 BOOL WINAPI MiniDumpWriteDump(
__in HANDLE hProcess,                       //  进程句柄,可以用GetCurrentProcess()获得
__in DWORD ProcessId,                       //  进程ID,可以用GetCurrentProcessId()获得
__in HANDLE hFile,                         // 待写入的dmp文件
__in MINIDUMP_TYPE DumpType,                   //  写入的dump信息类型,从MINIDUMP_TYPR中选择。
__in PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,     //  指向异常信息结构的指针,如果该值是NULL,将不会写入任何异常信息  
__in PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,   //   指向用户自定义信息块,可以为NULL
__in PMINIDUMP_CALLBACK_INFORMATION CallbackParam      //   指向回掉函数的扩展信息块,可以为NULL
);

  在MiniDumpWriteDump参数项中,比较重要的是异常信息块PMINIDUMP_EXCEPTION_INFORMATION,其结构如下:

 typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
DWORD ThreadId;                 //线程ID,可以用GetCurrentThreadId()获得
PEXCEPTION_POINTERS ExceptionPointers;   //指向异常信息指针,EXCEPTION_POINTER内包含了异常信息代码/flag等内容,异常发生时各寄存器状态和内容。用回掉函数的参数赋值即可
BOOL ClientPointers;              //TRUE和FALSE好像都可以,搞不清楚区别
} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;

  3:了解上述内容后,封装成类,方便移植。h文件:

 #pragma once
#include <string>
using namespace std;
class CCreateDump
{
public:
CCreateDump();
~CCreateDump(void);
static CCreateDump* Instance();
static long __stdcall UnhandleExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo);
//声明Dump文件,异常时会自动生成。会自动加入.dmp文件名后缀
void DeclarDumpFile(std::string dmpFileName = "");
private:
static std::string strDumpFile;
static CCreateDump* __instance;
};

  cpp文件:

 #include "StdAfx.h"
#include "CreateDump.h"
#include <DbgHelp.h>
#pragma comment(lib, "dbghelp.lib") CCreateDump* CCreateDump::__instance = NULL;
std::string CCreateDump::strDumpFile = ""; CCreateDump::CCreateDump()
{
} CCreateDump::~CCreateDump(void)
{ } long CCreateDump::UnhandleExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo)
{
HANDLE hFile = CreateFile(strDumpFile.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL );
if(hFile!=INVALID_HANDLE_VALUE)
{
MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = ::GetCurrentThreadId();
ExInfo.ExceptionPointers = ExceptionInfo;
ExInfo.ClientPointers = FALSE;
// write the dump
BOOL bOK = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL );
CloseHandle(hFile);
if (!bOK)
{
DWORD dw = GetLastError();
//写dump文件出错处理,异常交给windows处理
return EXCEPTION_CONTINUE_SEARCH;
}
else
{ //在异常处结束
return EXCEPTION_EXECUTE_HANDLER;
}
}
else
{
return EXCEPTION_CONTINUE_SEARCH;
}
} void CCreateDump::DeclarDumpFile(std::string dmpFileName)
{
SYSTEMTIME syt;
GetLocalTime(&syt);
char c[MAX_PATH];
sprintf_s(c,MAX_PATH,"[%04d-%02d-%02d %02d:%02d:%02d]",syt.wYear,syt.wMonth,syt.wDay,syt.wHour,syt.wMinute,syt.wSecond);
strDumpFile = std::string(c);
if (!dmpFileName.empty())
{
strDumpFile += dmpFileName;
}
strDumpFile += std::string(".dmp");
SetUnhandledExceptionFilter(UnhandleExceptionFilter);
} CCreateDump* CCreateDump::Instance()
{
if (__instance == NULL)
{
__instance = new CCreateDump;
}
return __instance;
}

  调用方法:加入头文件引用,在程序开始时写入

CCreateDump::Instance()->DeclarDumpFile("dumpfile");

  4:工程属性设置,VS2008工程属性->linker->debugging->Generate Debug Info选择yes,生成pdb文件。

  5:用vs2008打开dump文件,debug即可。

dump文件生成与调试(VS2008)的相关教程结束。

《dump文件生成与调试(VS2008).doc》

下载本文的Word格式文档,以方便收藏与打印。