VS2013生成及调试dump文件

在程序崩溃时,需要对异常的情况进行捕获,并捕获到的堆栈信息保持下来。Windows操作系统提供了一个API函数可以在程序crash之前有机会处理这些异常并生成dump文件。通过VS2013编辑器调试dump文件能快速定位到程序崩溃处的代码。

一、Windows API函数介绍

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter ( _In_LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
) ;

参数:lpTopLevelExceptionFilter ,函数指针。当异常发生时,且程序不处于调试模式(在vs或者别的调试器里运行)则首先调用该函数。

返回值:返回以前设置的回调函数

注意:在调用者进程中的所有线程已经将来创建的线程的异常处理链顶函数都会被修改为当前设定的回调函数。

二、demo代码

#include "stdafx.h"
#include <windows.h>

#include <stdlib.h>
using namespace std;

#pragma comment(lib, "Dbghelp.lib")
#include <Dbghelp.h>

namespace DumpFile
{
	void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)
	{
		// 创建Dump文件  
		HANDLE hDumpFile = CreateFile(lpstrDumpFilePathName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

		// Dump信息  
		MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
		dumpInfo.ExceptionPointers = pException;
		dumpInfo.ThreadId = GetCurrentThreadId();
		dumpInfo.ClientPointers = TRUE;

		// 写入Dump文件内容   
		MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

		CloseHandle(hDumpFile);
	}


	LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
	{
		return NULL;
	}

	BOOL PreventSetUnhandledExceptionFilter()
	{
		HMODULE hKernel32 = LoadLibrary(L"kernel32.dll");
		if (hKernel32 == NULL)
			return FALSE;


		void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");
		if (pOrgEntry == NULL)
			return FALSE;


		unsigned char newJump[100];
		DWORD dwOrgEntryAddr = (DWORD)pOrgEntry;
		dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far


		void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
		DWORD dwNewEntryAddr = (DWORD)pNewFunc;
		DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;


		newJump[0] = 0xE9;  // JMP absolute
		memcpy(&newJump[1], &dwRelativeAddr, sizeof(pNewFunc));
		SIZE_T bytesWritten;
		BOOL bRet = WriteProcessMemory(GetCurrentProcess(), pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten);
		return bRet;
	}

	LONG WINAPI UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS *pException)
	{
		TCHAR szFileName[MAX_PATH] = { 0 };
		SYSTEMTIME stLocalTime;
		GetLocalTime(&stLocalTime);
		wsprintf(szFileName, L"%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
			stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
			stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
			GetCurrentProcessId(), GetCurrentThreadId());

		CreateDumpFile(szFileName, pException);
		MessageBox(NULL, L"      运行中出现错误!   ", L"123456", MB_OK);

		FatalExit(-1);
		return EXCEPTION_CONTINUE_SEARCH;
	}

	void RunCrashHandler()
	{
		SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);
		PreventSetUnhandledExceptionFilter();
	}
};

#define ExceptionDumpFile() DumpFile::RunCrashHandler();

int _tmain(int argc, _TCHAR* argv[])
{
	ExceptionDumpFile();
	char* a = nullptr;
	*a = 1;
	return 0;
}

三、工程属性配置

1、打开工程->属性->链接器->调试->生成调试信息,修改成【是】(如下图)。

 2、打开工程->属性->C/C++->常规->调试信息格式,修改成【程序数据库】(如下图)。注意:如果在这里不修改成【程序数据库】,在调试dump文件时无法定位到源文件代码中的。

 四、VS2013调试dump文件

1、用VS2013打开dump文件,选择【设置符号路径】->【调试】->【符号】,把pdb、exe、dll文件路径添加到下图位置中。

 2、添加源代码文件

1、选择【视图】->【解决方案资源管理器】,把解决方案生成出来。如下图:

2、选择【解决方案】->右键->【属性】->【调试源文件】,添加源文件所在目录添加到下图所示位置中。

源码工程路径:https://download.csdn.net/download/jgliuhui1988/85330167

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值