程序在非调试模式下运行的时候对于程序的一些异常往往很难捕获到,导致无法定位到问题的所在,此时如果在程序发生异常的时候能够生成dmp文件,那么对于程序的异常定位将会有很大的帮助,下面介绍一下VS中如何生成dmp文件以及如何通过dmp定位到异常位置。

Dmp文件生成

在项目中新建类文件LCreateDump,具体代码如下

.h文件

#pragma once
#include <QObject>
#include <string>
#include <memory>
using namespace std;

class LCreateDump : public QObject
{
	Q_OBJECT

public:
	LCreateDump(QObject *parent=nullptr);
	~LCreateDump();

	static LCreateDump* Instance();
	static long __stdcall UnhandleExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo);
	//创建Dump文件,异常时会自动生成,传入存放的路径
	void DeclarDumpFile(std::string dmpFileName = "");
private:
	static std::string			    m_strDumpFile;
	static shared_ptr<CCreateDump*>    m_sptrInstance;
};

.cpp文件

#include "CCreateDump.h"
#include <Windows.h>
#include <DbgHelp.h>
#include <codecvt>
#pragma comment(lib,  "dbghelp.lib")

std::shared_ptr<LCreateDump*>  LCreateDump::m_sptrInstance = make_shared<LCreateDump*>();
std::string LCreateDump::m_strDumpFile = "";

LCreateDump::LCreateDump(QObject *parent)
	: QObject(parent)
{
}

LCreateDump::~LCreateDump()
{
}

long  LCreateDump::UnhandleExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo)
{
	std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converterX;
	std::wstring dumpFile = converterX.from_bytes(m_strDumpFile.c_str());
	HANDLE hFile = CreateFile(dumpFile.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 LCreateDump::DeclarDumpFile(std::string dmpFileName)
{
	SYSTEMTIME syt;
	GetLocalTime(&syt);
	char szTime[MAX_PATH];
	sprintf_s(szTime, MAX_PATH, "[%04d-%02d-%02dT%02d-%02d-%02d]", syt.wYear, syt.wMonth, syt.wDay, syt.wHour, syt.wMinute, syt.wSecond);
	m_strDumpFile = dmpFileName + std::string(szTime);
	m_strDumpFile += std::string(".dmp");
	SetUnhandledExceptionFilter(UnhandleExceptionFilter);
}

LCreateDump* LCreateDump::Instance()
{
	if (*m_sptrInstance == NULL)
	{
		m_sptrInstance = make_shared<LCreateDump*>(new LCreateDump());
	}
	return *m_sptrInstance;
}

Pdb文件生成

Vs在debug模式下会自动生成pdb文件,但是在release模式下默认是不生成pdb文件的,此时可以通过修改属性来生成。

1、在项目上右键-属性-C/C++-常规,设置调试信息格式

VS中生成及调试Dmp文件_c++

 2、在 属性-链接器-调试,设置生成调试信息

VS中生成及调试Dmp文件_c++_02

Dmp文件的使用

1、把exe、pdb、dmp文件放到同一目录中,

2、使用vs打开dmp文件

VS中生成及调试Dmp文件_#include_03

3、设置符号路径,添加pdb文件所在的路径

VS中生成及调试Dmp文件_#pragma_04

4、设置调试源文件路径,在解决方案上右键-属性-调试源文件

VS中生成及调试Dmp文件_2d_05

 5、最后点击 使用仅限本机进行调试 按钮,会自动定位到异常的代码行

VS中生成及调试Dmp文件_#pragma_06

 到此整个流程就结束了。