dump文件自动生成及调试

0 dump文件作用

Dump文件是进程的内存镜像,可以把程序的执行状态通过调试器保存到dump文件中。
主要用来在系统中出现异常或者崩溃的时候生成dump文件,然后用调试器进行调试,这样就可以把生产环境中程序崩溃后生成的dmp文件拷贝到程序员的开发机上,通过调试找到程序出错的位置。

1 dump文件生成

代码封装如下:

#ifndef CREATE_DUMP_H_
#define CREATE_DUMP_H_

#pragma once
#include <string>
#include <Windows.h>
#include <DbgHelp.h>
#include <codecvt>

#pragma comment(lib,  "dbghelp.lib")

class CCreateDump
{
public:
	CCreateDump();

	~CCreateDump(void);

	static CCreateDump* Instance();

	void CreateDumpFile(std::string str_dmp_file_name = "dumpfile");

private:
	static long __stdcall UnhandleExceptionFilter(_EXCEPTION_POINTERS* pt_exception_info);

	private:
	static std::string		m_st_str_dmp_file_name;
	static CCreateDump*		m_stp_instance;
};


CCreateDump* CCreateDump::m_stp_instance = nullptr;
std::string CCreateDump::m_st_str_dmp_file_name = "";

CCreateDump::CCreateDump()
{
}

CCreateDump::~CCreateDump(void)
{
}

CCreateDump* CCreateDump::Instance()
{
	if (!m_stp_instance) {
		m_stp_instance = new CCreateDump;
	}
	return m_stp_instance;
}

void CCreateDump::CreateDumpFile(std::string str_dmp_file_name)
{
	SYSTEMTIME sys_time;
	GetLocalTime(&sys_time);
	char c[MAX_PATH];
	sprintf_s(c, MAX_PATH, "%04d-%02d-%02d_%02d-%02d-%02d_", sys_time.wYear, sys_time.wMonth, sys_time.wDay, sys_time.wHour, sys_time.wMinute, sys_time.wSecond);
	m_st_str_dmp_file_name = std::string(c);
	if (!str_dmp_file_name.empty()) {
		m_st_str_dmp_file_name += str_dmp_file_name;
	}
	m_st_str_dmp_file_name += std::string(".dmp");
	SetUnhandledExceptionFilter(UnhandleExceptionFilter);
}

long  CCreateDump::UnhandleExceptionFilter(_EXCEPTION_POINTERS* pt_exception_info)
{
	std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converterX;
	std::wstring wstr_dmp_file_name = converterX.from_bytes(m_st_str_dmp_file_name.c_str());
	HANDLE h_dmp_file = CreateFile(wstr_dmp_file_name.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
	if (h_dmp_file != INVALID_HANDLE_VALUE) {
		MINIDUMP_EXCEPTION_INFORMATION   mini_dump_ex_info;
		mini_dump_ex_info.ThreadId = ::GetCurrentThreadId();
		mini_dump_ex_info.ExceptionPointers = pt_exception_info;
		mini_dump_ex_info.ClientPointers = FALSE;
		//   write   the   dump
		BOOL   b_ok = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h_dmp_file, MiniDumpNormal, &mini_dump_ex_info, nullptr, nullptr);
		CloseHandle(h_dmp_file);
		if (!b_ok) {
			DWORD dw = GetLastError();
			return EXCEPTION_CONTINUE_SEARCH;		//写dump文件出错处理,异常交给windows处理
		}
		else {   
			return EXCEPTION_EXECUTE_HANDLER;		 //在异常处结束
		}
	}
	else {
		return EXCEPTION_CONTINUE_SEARCH;
	}
	return EXCEPTION_EXECUTE_HANDLER;
}

#endif // !CREATE_DUMP_H_

测试demo如下:

#include "create_dump.h"
#include <iostream>

int main(void)
{
	CCreateDump::Instance()->CreateDumpFile();
	int* p = nullptr;
	*p = 5;
	std::system("pause");
	return 0;
}

2 dump文件调试

编译并运行.exe可执行程序后,将在.exe同目录下生成.dmp文件。

注:如果在Visual Studio中直接运行代码,程序将直接崩溃,不会生成.dmp文件,因为Visual Studio调试器已经捕获了异常,不会再进入设置的异常捕获函数UnhandleExceptionFilter

.dmp,.exe(.dll),.pdb文件放在同一目录,通过Visual Studio打开.dmp文件,如下:
image.png
点击“使用仅限本机进行调试”,调试结果如下,给出了报错的位置及调用堆栈信息:
image.png
.exe(.dll),.pdb文件与.dmp文件不在同一目录,那么需要设置.exe(.dll),.pdb的路径,如下:
image.png
image.png
否则将会出现未找到或加载.exe(.dll),.pdb的情况,如下:
image.png

3 注意事项

3.1 exe/dll与pdb的版本必须一致

编译生成的.exe/.dll文件与.pdb文件版本必须一致,否则也会出现未找到或未加载.exe(.dll),.pdb的情况。
调试器是如何来判别各文件版本是否一致呢?
每次链接生成.exe或者.dll时,链接器都将产生一个唯一的GUID,然后将其写入到.pdb文件和.exe文件,每次重新编译,即使所有代码均没有变化,GUID也不同。调试器加载这两个文件的时候将检查两者的GUID,如果一致就表示他们匹配。
也就是说,dump文件调试所需的.exe/.dll.pdb文件,必须是由编译器在同一次编译过程中生成的,因此要妥善保管好.exe/.dll.pdb文件。

4 参考文献

  1. https://blog.csdn.net/sesiria/article/details/117521736
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值