Windows c++ 崩溃时生成 dump 文件

1、背景

在做 Windows 客户端应用开发时,难免遇到程序的崩溃,当程序在 debug 崩溃时,我们可以直接定位到崩溃点,但是当程序打包成 release 发布时,难免也会遇到一些崩溃问题(当然在开发时要尽量保障程序的稳定性),一般遇到这样的崩溃,我们就需要使用 dump 文件加上符号表文件来进行调试程序,所以一般的 CI 除了将 exe 上传以外还需要将符号表信息上传。

2、在代码中生成 dump 文件

#include <Windows.h>
#include <DbgHelp.h>
#include <tchar.h>
#include <shlobj_core.h>
#include <io.h>
#include <direct.h>

#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>

// 生成 dump 文件的目录名称
const std::string& kDUMPDir = "\\MyDumpTest";
typedef BOOL(WINAPI * MiniDumpWriteDumpT)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
	PMINIDUMP_EXCEPTION_INFORMATION, PMINIDUMP_USER_STREAM_INFORMATION, PMINIDUMP_CALLBACK_INFORMATION);

int CreateDump(PEXCEPTION_POINTERS pointers) {
	HMODULE dbg_help = LoadLibrary("DbgHelp.dll");
	if (NULL == dbg_help) {
		return EXCEPTION_CONTINUE_EXECUTION;
	}

	MiniDumpWriteDumpT dump_writer = (MiniDumpWriteDumpT)GetProcAddress(dbg_help, "MiniDumpWriteDump");
	if (NULL == dump_writer) {
		FreeLibrary(dbg_help);
		return EXCEPTION_CONTINUE_EXECUTION;
	}

	// 获取到 %localappdata% 目录
	char buffer[256] = "";
	SHGetSpecialFolderPathA(NULL, buffer, CSIDL_LOCAL_APPDATA, FALSE);

	std::string dump_dir = buffer;
	dump_dir += kDUMPDir;
	std::cout << "dump_dir:" << dump_dir << std::endl;
	// 判断文件夹是否存在
	if (_access(dump_dir.c_str(), 0) == -1) {
		// 如果不存在,那么就创建
		_mkdir(dump_dir.c_str());
	}

	// dmp 文件名
	SYSTEMTIME local_time;
	GetLocalTime(&local_time);

	std::stringstream ss;
	ss << dump_dir << "\\dump-" << local_time.wYear << "-" <<
		std::setw(2) << std::setfill('0') << local_time.wMonth << "-" <<
		std::setw(2) << std::setfill('0') << local_time.wDay << "-" <<
		std::setw(2) << std::setfill('0') << local_time.wHour <<
		std::setw(2) << std::setfill('0') << local_time.wMinute <<
		std::setw(2) << std::setfill('0') << local_time.wSecond << ".dmp";

	HANDLE dump_file = CreateFile(ss.str().c_str(), GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
	if (INVALID_HANDLE_VALUE == dump_file) {
		FreeLibrary(dbg_help);
		return EXCEPTION_CONTINUE_EXECUTION;
	}

	// 写入 dmp 文件
	MINIDUMP_EXCEPTION_INFORMATION param;
	param.ThreadId = GetCurrentThreadId();
	param.ExceptionPointers = pointers;
	param.ClientPointers = FALSE;

    // MiniDumpWithDataSegs : dump 文件的类型,一般这个就够了
    // MiniDumpNormal 比较小 MiniDumpWithFullMemory 比较大
	dump_writer(GetCurrentProcess(), GetCurrentProcessId(),
		dump_file, MiniDumpWithDataSegs, (pointers ? &param : NULL), NULL, NULL);

	// 释放文件
	CloseHandle(dump_file);
	FreeLibrary(dbg_help);
	return 0;
}

LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS pointers) {
	// 这里做一些异常的过滤或提示
	if (IsDebuggerPresent()) {
		return EXCEPTION_CONTINUE_SEARCH;
	}
	return CreateDump(pointers);
}
int main(int argc, char *argv[]) {
	SetUnhandledExceptionFilter(ExceptionFilter);
	// 执行程序
	int* p = nullptr;
	p[0] = 1;
	std::cout << "end" << std::endl;
	getchar();
	return 0;
}

3、运行程序

这里运行程序,不是在 vs 里面运行,而是指双击 exe 进行运行,然后程序会 crash ,这个时候在对应目录下面查看是否有生成 dump 文件

下来就可以使用 windbg 或者 vs 调试 dump 文件了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C/C++应用程序在遇到宕机或崩溃,可以生成dump文件,用于分析和排查问题。dump文件是一个二进制文件,包含了应用程序当前状态的所有信息,例如寄存器的值、堆栈信息、内存快照等。 生成dump文件的过程通常需要在宕机发生进行设置,在代码中添加相应的处理逻辑。可以使用操作系统提供的工具或使用一些第三方库来生成dump文件。 在Windows操作系统中,可以使用Windows Error Reporting(WER)来生成dump文件。WER会通过注册表设置或程序运行设置来配置生成dump文件的方式和路径。可以通过指定参数和设置注册表来控制生成dump文件的级别(如只生成小型或完全的dump文件)。当应用程序发生崩溃,WER会拦截并触发生成dump文件。使用WER生成dump文件可以在调试器中打开进行分析。 在Linux操作系统中,可以使用glibc库的backtrace机制来生成dump文件。通过设置信号处理函数,将崩溃的堆栈信息写入文件。可以通过注册信号处理函数,并在函数中使用backtrace和backtrace_symbols将堆栈信息写入文件。 除了使用操作系统提供的工具和机制,还可以使用一些第三方库来生成dump文件,如Google Crashpad和Breakpad等。这些库提供了更灵活和可定制的选项,可以在崩溃发生执行回调函数,并根据需求生成dump文件。 总之,通过生成dump文件,我们可以在程序崩溃获取并保存关键的调试信息,有助于分析和定位问题的根源,提高应用程序的稳定性和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值