C++程序中dump文件生成方法详解

最近项目中新作成了一个动态链接库,长时间运行后,偶尔会崩溃。根据log分析,被调用的动态库函数最外层catch到了这个异常,但是不能定位哪里出了问题。另外虽然上层exe是有dump文件输出处理的,但是在C++中,如果异常被捕获并处理的情况下,系统就不会生成dump文件了。如果仍希望在try-catch块中捕获异常的同时生成dump文件,就必须在catch块中手动调用生成dump文件的函数。这样可以在异常被捕获后仍然生成dump文件以供后续分析。本文详细介绍下怎么生成dump文件。


链接库

Windows平台上用Windows调试帮助库中的函数MiniDumpWriteDump来生成dump文件。

dbghelp.h头文件

#include <dbghelp.h>

dbghelp.lib库

项目【属性】→【链接器】→【输入】→【附加依赖项】→ 添加dbghelp.lib
在这里插入图片描述


dump生成原理:

生成dump文件的原理是在未处理异常发生时,系统调用设置的未处理异常过滤器回调函数,并将异常信息传递给这个回调函数。回调函数可以利用这些异常信息,如异常指针和线程ID,来创建一个包含应用程序状态快照的dump文件。这个快照包括了应用程序的内存、寄存器状态、堆栈信息等,可以帮助开发人员在应用程序崩溃时进行调试和分析。

SetUnhandledExceptionFilter函数是Windows平台上用于设置未处理异常过滤器的函数。
MiniDumpWriteDump函数是Windows平台上用于输出dump文件的函数。


代码实例

dump文件名和输出路径设置

dump文件名和输出路径没有什么硬性要求,根据各自程序的需求来即可。

本文
dump文件名:当前模块名+当前时间
dump输出路径:当前模块所在同级目录

// 获取当前模块的路径
std::string GetCurrentModuleFilePath()
{char buffer[MAX_PATH];GetModuleFileName(nullptr, buffer, MAX_PATH);return std::string(buffer);
}// 获取当前模块的名字(不含后缀)
std::string GetModuleName(const std::string& filePath)
{std::string fileName = "";size_t lastSlash = filePath.find_last_of("\\");size_t lastDot = filePath.find_last_of(".");if (lastSlash != std::string::npos && lastDot != std::string::npos&& lastDot > lastSlash){fileName = filePath.substr(lastSlash + 1, lastDot - lastSlash - 1);}return fileName;
}// 获取当前时间(2023-11-23_18-42-345形式)
std::string GetCurrentTimeWithFormat() 
{SYSTEMTIME st;GetLocalTime(&st);std::string fileName;fileName = std::to_string(st.wYear) + "-" + std::to_string(st.wMonth) + "-" + std::to_string(st.wDay) + "_" + std::to_string(st.wHour) + "-" + std::to_string(st.wMinute) + "-" + std::to_string(st.wSecond) + "-" + std::to_string(st.wMilliseconds);return fileName;
}

未处理异常过滤器回调函数

// 未处理异常过滤器回调函数																																		
LONG WINAPI UnhandledExceptionFilterCallback(EXCEPTION_POINTERS *pExceptionPointers)
{std::string moduleFilePath = GetCurrentModuleFilePath();std::string moduleFileName = GetModuleName(moduleFilePath);std::string currentTime = GetCurrentTimeWithFormat();// 获取dump文件名字std::string dumpFileName = moduleFileName + "_" + currentTime + ".dmp";// 获取dump文件输出路径std::string dumpFilePath = "";size_t pos = moduleFilePath.find_last_of("\\");if (pos != std::string::npos){dumpFilePath = moduleFilePath.substr(0, pos + 1) + dumpFileName;}else{dumpFilePath = dumpFileName;}// 创建dump文件HANDLE hDumpFile = CreateFile(dumpFilePath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);if (hDumpFile != INVALID_HANDLE_VALUE) {MINIDUMP_EXCEPTION_INFORMATION miniDumpExceptionInfo;miniDumpExceptionInfo.ThreadId = GetCurrentThreadId();           // 表示引发异常的线程的线程标识符miniDumpExceptionInfo.ExceptionPointers = pExceptionPointers;    // 指向包含有关异常上下文信息的指针的指针miniDumpExceptionInfo.ClientPointers = FALSE;                    // 指示是否包含有关客户端指针的信息。如果设置为 TRUE,则会包含客户端指针的信息;如果设置为 FALSE,则不会包含客户端指针的信息。/*Note在 Windows 编程中,客户端指针通常指的是指向客户端应用程序内存中的数据结构或对象的指针。当生成 dump 文件时,包含客户端指针的信息可能会暴露应用程序的内部结构和数据,可能包含敏感信息,因此在某些情况下可能需要禁用客户端指针的信息以保护隐私和安全。*/// 根据自己的需要指定dump文件的类型,一般MiniDumpNormal就可MINIDUMP_TYPE miniDumpType = (MINIDUMP_TYPE)(MiniDumpNormal| MiniDumpWithHandleData| MiniDumpScanMemory| MiniDumpWithProcessThreadData| MiniDumpWithThreadInfo);// 写入dump文件BOOL bMiniDumpWriteSuccessful = MiniDumpWriteDump(GetCurrentProcess(),     // 获取进程句柄GetCurrentProcessId(),   // 获取进程IDhDumpFile,               // 要写入的dump文件句柄miniDumpType,            // 指定dump文件的类型&miniDumpExceptionInfo,  // 指向包含异常信息的结构体指针NULL,                    // 指向用户自定义数据的结构体指针NULL                     // 指向回调函数的结构体指针);                      CloseHandle(hDumpFile);}return EXCEPTION_EXECUTE_HANDLER;
}

未处理异常过滤器函数的调用

未处理异常过滤器函数的调用应该在main函数(MFC程序的话是InitInstance函数)入口或者dll函数的入口。

int main(){// 设置未处理异常过滤器SetUnhandledExceptionFilter(UnhandledExceptionFilterCallback);// 程序逻辑//......
}

注意事项

在生成dump文件时,有一些注意事项需要考虑:

  • 文件大小:生成的dump文件可能会很大,特别是在应用程序的内存占用较大时。确保生成dump文件的目标位置有足够的磁盘空间。
  • 调试符号:为了更好地分析dump文件,通常需要应用程序的调试符号(PDB文件)。确保在生成dump文件时,同时保存了相关的调试符号信息。
  • 版本一致性:在分析dump文件时,确保使用与生成dump文件时相同版本的调试符号和源代码。否则,可能会导致分析结果不准确。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/163931.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何利用Python进行数据归一化?

1. 知识简介 数据归一化是数据预处理的一项重要步骤&#xff0c;它对于提高模型性能、加速模型训练、避免数值计算问题以及提高模型的泛化能力都具有重要作用。进行数据归一化可以起到以下作用&#xff1a;消除量纲影响&#xff0c;加速模型收敛&#xff0c;提高模型性能&…

硅谷大宽服务器:引领互联网新时代的核心技术

在当今这个信息爆炸的时代&#xff0c;数据已经成为了企业和个人的重要资产。服务器作为数据的存储和处理中心&#xff0c;其重要性不言而喻。硅谷大宽服务器以其卓越的性能、稳定的运行和优质的服务&#xff0c;赢得了全球众多企业和个人的信赖和选择。 硅谷大宽服务器的特点…

图解分库分表

中大型项目中&#xff0c;一旦遇到数据量比较大&#xff0c;小伙伴应该都知道就应该对数据进行拆分了。有垂直和水平两种。 垂直拆分比较简单&#xff0c;也就是本来一个数据库&#xff0c;数据量大之后&#xff0c;从业务角度进行拆分多个库。如下图&#xff0c;独立的拆分出…

Redisson分布式锁实现原理

Redisson主要解决一下问题 重入问题&#xff1a;重入问题是指 获得锁的线程可以再次进入到相同的锁的代码块中&#xff0c;可重入锁的意义在于防止死锁&#xff0c;比如HashTable这样的代码中&#xff0c;他的方法都是使用synchronized修饰的&#xff0c;假如他在一个方法内&a…

解决Spring Boot应用在Kubernetes上健康检查接口返回OUT_OF_SERVICE的问题

现象 在将Spring Boot应用部署到Kubernetes上时&#xff0c;健康检查接口/healthcheck返回的状态为{"status":"OUT_OF_SERVICE","groups":["liveness","readiness"]}&#xff0c;而期望的是返回正常的健康状态。值得注意的…

VTK物体表面画贴合线条

1、自由画线 2、曲线拟合画线 3、三点闭合曲线

Docker Compose部署微服务项目实战讲解

一、Docker Compose简介 当需要在多个容器之间协调和管理应用程序时&#xff0c;Docker Compose是一个非常有用的工具。它允许通过一个配置文件来定义、配置和启动多个 Docker 容器&#xff0c;使得整个应用程序的部署变得更加简单和一致。以下是 Docker Compose 的一些重要概…

Linux使用宝塔面板+Discuz+cpolar内网穿透工具搭建可公网访问论坛

Linux宝塔面板搭建Discuz论坛&#xff0c; 并内网穿透实现公网访问 文章目录 Linux宝塔面板搭建Discuz论坛&#xff0c; 并内网穿透实现公网访问前言1.安装基础环境2.一键部署Discuz3.安装cpolar工具4.配置域名访问Discuz5.固定域名公网地址6.配置Discuz论坛 前言 Crossday Di…

【 图片加载】Vue前端各种图片引用

文章目录 一、图片作为js常量&#xff08;常作为配置项的值 &#xff09;1、在线链接2、本地图片 二、图片img标签1、一般的src2、动态的src用require3、src可以接收二进制文件blob&#xff08;如后端返回的、a-upload传的图片) 三、背景图片 一、图片作为js常量&#xff08;常…

8款那些年救过我的数据文件恢复软件 - 误删除重要文件的“后悔药”

无论您在保存备份方面多么小心&#xff0c;灾难有时还是会发生。有时您的备份软件无法按预期运行。 如果您的外部驱动器靠近您的设备&#xff0c;发生火灾/洪水/故障时&#xff0c;有时备份会与原始文件一起丢失。即使是云存储也不能避免故障。 还有一个事实是&#xff0c;我…

C++设计模式之工厂模式(上)——简单工厂模式

工厂模式 概述简单工厂模式介绍示例示例使用运行结果缺点 概述 工厂模式属于一种创建型设计模式。其可以分为简单工厂模式&#xff0c;工厂模式和抽象工厂模式。工厂模式分为上、中、下三篇&#xff0c;本篇主要介绍简单工厂模式。 简单工厂模式 介绍 简单工厂模式可以理解…

二叉树题目:具有所有最深结点的最小子树

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;具有所有最深结点的最小子树 出处&#xff1a;865. 具有所有最深结点的最小子树 难度 5 级 题目描述 要求 给定…

HCIP-六、OSPF-2 综合实验

六、OSPF-2 综合实验 实验拓扑实验需求及解法1.设备名称和部分IP地址已配置2.所有设备运行OSPF&#xff0c;进程号为13.区域间路由汇总4.外部路由汇总5.下发默认路由6. 虚链路 实验拓扑 实验需求及解法 本实验模拟OSPF综合型网络&#xff0c;按照以下需求完成实验。 1.设备名…

EventLog Analyzer:强大的日志管理与分析工具

随着企业网络规模的扩大和信息系统的复杂化&#xff0c;安全日志管理和分析成为了至关重要的一环。在这个背景下&#xff0c;EventLog Analyzer崭露头角&#xff0c;成为一款备受推崇的日志管理与分析工具。本文将介绍EventLog Analyzer的主要特点、功能以及为企业带来的实际价…

IDEA安装教程

文章目录 1 下载IntelliJ IDEA2 安装3 IDEA配置4 创建项目 1 下载IntelliJ IDEA ​ 官方网站上下载最新版本的IntelliJ IDEA。官方网站提供了两个版本&#xff1a;Community版和Ultimate版。 Community版是免费的&#xff0c;适用于个人和非商业用途。Ultimate版则需要付费购…

Exception in thread “消费者“ java.lang.IllegalMonitorStateException

这两天学习生产者消费者模型的时候&#xff0c;使用Java线程来实现&#xff0c;出现了一个问题“Exception in thread "消费者" java.lang.IllegalMonitorStateException”&#xff0c;并且&#xff0c;线程不结束。报错图片如下&#xff1a; 那我们怎么解决呢&…

竞赛选题 题目: 基于深度学习的疲劳驾驶检测 深度学习

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

河北专升本(微机原理)

目录 第一章&#xff1a;计算机基础与数制转化 1. 进制运算基础 2. 常用编码形式 3. 计算机系统的组成及其工作原理 4. 微机系统主要技术指标 第二章&#xff1a;8086微处理器及其系统 1. 8086微处理器&#xff08;CPU&#xff09; 2. 8086的存储器及I/O组织 3. 8086系…

vue中的列表过滤和列表排序

列表过滤 <body><div id"root"><!--输入框用于模糊查询--><input type"text" placeholder"请你输入名字" v-model"name"><ul><!--in可以换成of--><li v-for"(p,index) in persons" …