Windows上使用dump文件调试

dump文件

dump文件记录当前程序运行某一时刻的信息,包括内存,线程,线程栈,变量等等,相当于调试程序时运行到某个断点上,把程序运行的信息记录下来。可以通过Windbg打开dump,查看程序运行的变量等,来调试程序。

在Liunx上也有类似的技术,Coredump,具体可以参考:coredump详解_coredump文件分析_贺二公子的博客-CSDN博客

dump 文件分类

dump可以分为 minidump 和 Full dump

minidump通常只包含了一些关键信息,一般比较小,通常只要几MB,

Full dump包含了程序运行时的所有信息,包括程序的所有内存,一般有几十MB到几GB。

minidump虽然只包含了部分信息,但这些信息大部分情况足够用于调试,所以通常都是使用minidump调试

生成dump文件

通过任务管理器导出

在进程上右击->创建内存转储文件,这样创建的是Full dump

通过Process Explorer导出

Process Explorer - Sysinternals | Microsoft Learn

选择对应的进程->Process->Create Dump,然后选择要创建minidump 还是 Full Dump

使用MiniDumpWriteDump函数序生成 

#include <iostream>
#include <Windows.h>
#include <Dbghelp.h>
#include <thread>
#pragma comment(lib, "Dbghelp.lib")void createMinidump()
{wchar_t DumpPath[MAX_PATH] = {0};SYSTEMTIME SystemTime;GetLocalTime(&SystemTime);WCHAR szExeFileName[256] = {0};GetModuleFileNameW(nullptr, szExeFileName, 99);wsprintfW(DumpPath, L"%s_%d-%d-%d_%d-%d-%d.dmp", szExeFileName, SystemTime.wYear, SystemTime.wMonth,SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);HANDLE file = CreateFileW(DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);if (file != INVALID_HANDLE_VALUE){DWORD Flags = MiniDumpWithHandleData |MiniDumpWithUnloadedModules |MiniDumpScanMemory|MiniDumpWithIndirectlyReferencedMemory |MiniDumpWithProcessThreadData |MiniDumpWithThreadInfo;if (MiniDumpWriteDump(GetCurrentProcess(), (DWORD) GetCurrentProcessId(), file,(MINIDUMP_TYPE) (Flags),nullptr, nullptr, nullptr) != 0){std::cout << "Create Minidump successful!! file:";std::wcout << DumpPath << std::endl;}else{std::cout << "Create Minidump failed!!" << std::endl;}}CloseHandle(file);
}void createFullDump()
{wchar_t DumpPath[MAX_PATH] = {0};SYSTEMTIME SystemTime;GetLocalTime(&SystemTime);WCHAR szExeFileName[256] = {0};GetModuleFileNameW(nullptr, szExeFileName, 99);wsprintfW(DumpPath, L"%s_%d-%d-%d_%d-%d-%d_full.dmp", szExeFileName, SystemTime.wYear, SystemTime.wMonth,SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);HANDLE file = CreateFileW(DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);if (file != INVALID_HANDLE_VALUE){const DWORD Flags = MiniDumpWithFullMemory |MiniDumpWithFullMemoryInfo |MiniDumpWithHandleData |MiniDumpWithUnloadedModules |MiniDumpWithProcessThreadData |MiniDumpWithThreadInfo;if (MiniDumpWriteDump(GetCurrentProcess(), (DWORD) GetCurrentProcessId(), file,(MINIDUMP_TYPE) (Flags),nullptr, nullptr, nullptr) != 0){std::cout << "Create Full dump successful!! file:";std::wcout << DumpPath << std::endl;}else{std::cout << "Create Full dump failed!!" << std::endl;}}CloseHandle(file);
}

程序崩溃时自动导出Dump

我们希望程序运行崩溃时可以自动导出dump,这样可以通过分析dump文件找到崩溃原因。

程序崩溃很多情况都是由异常引起的,Windows提供了SetUnhandledExceptionFilter函数用来设置一个函数指针,用于处理未处理的异常,可以在这个函数中导出Dump文件。

步骤:

1. 准备一个处理异常的函数,并在其中导出dump。异常处理函数有一个参数,这个参数记录了当前异常信息,这个异常信息可以一起随dump文件导出,方便后续查找Bug

LONG WINAPI DumpException(EXCEPTION_POINTERS* info)
{std::cout << "DumpException, Thread ID:"<< std::this_thread::get_id() << std::endl;std::cout << "Exception: 0x" << std::hex << info->ExceptionRecord->ExceptionCode << std::endl;wchar_t DumpPath[MAX_PATH] = { 0 };SYSTEMTIME SystemTime;GetLocalTime(&SystemTime);WCHAR szExeFileName[100] = { 0 };GetModuleFileNameW(nullptr, szExeFileName, 99);wsprintfW(DumpPath, L"%s_%d-%d-%d_%d-%d-%d_crash.dmp", szExeFileName, SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);HANDLE file = CreateFileW(DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);if (file != INVALID_HANDLE_VALUE){MINIDUMP_EXCEPTION_INFORMATION mdei;mdei.ThreadId = (DWORD)GetCurrentThreadId();mdei.ExceptionPointers = info;mdei.ClientPointers = 0;DWORD Flags = MiniDumpWithHandleData |MiniDumpWithUnloadedModules |MiniDumpScanMemory|MiniDumpWithIndirectlyReferencedMemory |MiniDumpWithProcessThreadData |MiniDumpWithThreadInfo;//        Flags = MiniDumpWithFullMemory |
//                MiniDumpWithFullMemoryInfo |
//                MiniDumpWithHandleData |
//                MiniDumpWithUnloadedModules |
//                MiniDumpWithThreadInfo;if (MiniDumpWriteDump(GetCurrentProcess(), (DWORD)GetCurrentProcessId(), file,(MINIDUMP_TYPE)(Flags),&mdei, nullptr, nullptr) != 0){std::cout << "Create Crash dump successful!! file:";std::wcout << DumpPath << std::endl;CloseHandle(file);return EXCEPTION_EXECUTE_HANDLER;}}std::cout << "Create Crash dump failed!!" << std::endl;CloseHandle(file);return EXCEPTION_CONTINUE_SEARCH;
}

2. 在程序启动时设置异常处理函数

int main()
{std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;LPTOP_LEVEL_EXCEPTION_FILTER oldExceptionFilter = nullptr;oldExceptionFilter = SetUnhandledExceptionFilter(&DumpException);// ... ...// ... ...}

PS

1. 这里是通过异常捕获生成dump,如果是调用abort,exit,TerminateProcess, TerminateThread函数,这些函数会立即结束进程,所以不会生成dump。

2. SetUnhandledExceptionFilter是全局的,只需设置一次,设置后对所有线程有效。SetUnhandledExceptionFilter有些异常捕获不到。

3. 可以使用第三方库捕获崩溃事件,例如:crashrpt,google breakpad,qBreakpad,Crashpad

UnhandledExceptionFilter未处理的异常

Windows中所有的函数都是从BaseThreadStart函数开始运行

VOID BaseThreadStart(PTHREAD_START_ROUTINE pfnStartAddr, PVOID pvParam) {
__try {
ExitThread((pfnStartAddr)(pvParam));
}
__except (UnhandledExceptionFilter(GetExceptionInformation())) {
ExitProcess(GetExceptionCode());
}
// NOTE: We never get here
}

这里的函数UnhandledExceptionFilter用来处理线程中捕获的未处理的异常,调用SetUnhandledExceptionFilter就是用来设置这个函数。

这里的__try{}__except{} 是 Windows系统的结构化异常处理(SEH),具体参考 《Windows核心编程第五版》——第24章

使用VS调试Dump文件

调试Dump文件,dump文件以外,还需要pdb符号文件,pdb符号文件是编译时和exe程序同时生成的,默认情况下Debug版本会生成符号文件,Release文件不生成符号文件,Release模式下需要手动打开生成符号文件。

打开Dump文件

文件->打开->文件,选择dump文件

设置符号文件

符号文件(pdb)必须保证时和exe同时生成的,且不能改文件名,否则会加载失败

有两种方法

1. 把符号文件和dump文件放在同一个目录下,VS在加载dump时会读取dump目录下的符号文件。

2. 通过 【工具->选项->调试->符号】设置符号文件路径。

调试 

点击右上角的 【使用 混合 进行调试】,则可以查看dump文件的内容,如果有异常会显示对应异常位置。整体效果和调试模式下运行出现异常是一样的。

 

使用Windbg调试Dump文件

Windbg 下载 Install WinDbg - Windows drivers | Microsoft Learn

Windbg打开dump后会提示是否有异常

调试步骤:

1. 设置符号文件 【文件->settings->debuging settings】

2. 输入 .ecxr 命令

3. 输入 kn 命令

查看exe编译时间

lm vm test_win*

通过这个时间可以去查找exe对应的pdb文件 

完整代码例子:小康6650/StudyProject - Gitee.com

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

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

相关文章

在IDEA中创建properties配置文件

第一步&#xff1a;在 src路径下找到resources文件 第二步&#xff1a;右击选择新建Resource Bundle配置文件 第三步&#xff1a;为Resource Bundle配置文件命名 完成创建

第十课:Qt 字符编码和中文乱码相关问题

功能描述&#xff1a;最全的 Qt 字符编码相关知识以及中文乱码的原因与解决办法 一、字符编码种类 ASCII 码 美国人对信息交流的编码&#xff0c;包括 26 个字母&#xff08;大小写&#xff09;、数字和标点符号等&#xff0c;用一个字节&#xff08;8 位&#xff09;表示这些…

vue-组件库-storybook:理解storybook、实践

一、理解 storybook Storybook是一个开源的工具&#xff0c;可以帮助前端开发者更好地构建、测试和展示组件。 具体来说&#xff0c;Storybook可以做以下几件事情&#xff1a; 1、为每个组件提供一个独立的页面&#xff0c;可以快速展示或调试组件。 2、管理多个组件&#x…

vue利用 sortable 完成表格拖拽

先讲一下vue2&#xff0c;使用sortable完成表格拖拽【不只是表格&#xff0c;div也可以实现&#xff0c;但我项目中是表格拖拽】 github地址 安装 npm install sortablejs --save使用 &#xff08;我的项目中是拖拽一个小按钮移动&#xff0c;而不是整行&#xff09; <te…

VMware虚拟机Ubuntu无法连接网络的解决方法

一、解决办法 网络适配器设置 终端依次执行下面命令即可 sudo nmcli networking off sudo nmcli networking onsudo service network-manager start #或者 sudo service NetworkManager start成功出现这个图标&#xff0c;即代表网络连接成功。

单元测试到底是什么?应该怎么做?

一、什么是单元测试&#xff1f; 单元测试&#xff08;unit testing&#xff09;&#xff0c;是指对软件中的最小可测试单元进行检查和验证。至于“单元”的大小或范围&#xff0c;并没有一个明确的标准&#xff0c;“单元”可以是一个函数、方法、类、功能模块或者子系统。 …

滴滴Ceph分布式存储系统优化之锁优化

摘自&#xff1a;https://mp.weixin.qq.com/s/oWujGOLLGItu1Bv5AuO0-A 2020-09-02 21:45 0.引言 Ceph是国际知名的开源分布式存储系统&#xff0c;在工业界和学术界都有着重要的影响。Ceph的架构和算法设计发表在国际系统领域顶级会议OSDI、SOSP、SC等上。Ceph社区得到Red Hat…

指针、数组、sizeof、strlen相关知识与练习题目

目录 前提回顾&#x1f50d;&#xff1a; 关于一维数组&#x1f92e;&#xff1a; 关于二维数组&#x1f600;&#xff1a; sizeof与strlen&#x1f415;&#xff1a; sizeof&#x1f3c0;&#xff1a; strlen&#x1f413;&#xff1a; 相关练习&#x1f4da;&#xff1a…

numpy基础知识

文章目录 安装numpynumpy的ndarray对象ndarray 和 list 效率比较创建一/二维数组ndarray的常用属性调整数组形状ndarray转list numpy的数据类型数组的运算数组和数的计算数组和数组的计算 数组的轴数组的索引和切片数组的与或非和三目运算符numpy的插入、删除、去重插入删除去重…

高并发内存池(threadcache)[1]

高并发内存池 分层处理 thread cache 定义一个公共的FreeList管理切分的小空间 static void*& NextObj(void* obj) {return *(void**)obj; }//管理切分好的小对象的自由链表 class FreeList { public:void Push(void* obj){assert(obj);//头插//*(void**)obj _freeLis…

Linux工具【2】(调试器gdb、项目自动化构建工具make/Makefile)

gdb、make/Makefile 引言调试器gdb介绍常用指令 自动化构建工具make/Makefile介绍使用依赖关系与依赖方法编辑Makefile伪目标 总结 引言 在上一篇文章中介绍了Linux中的编辑器vim与编译器gcc与g&#xff1a; 戳我看vim与gcc详解哦 在本篇文章中将继续来介绍Linux中的工具&…

js ajax 国内快速 映像

ajax 快速 映像 https://www.bootcdn.cn/ axios入门和axios基本请求方式 https://blog.csdn.net/m0_68997646/article/details/127438174 使用 jsDelivr CDN: <script src"https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>因为我们国…

【Linux命令详解 | ssh命令】 ssh命令用于远程登录到其他计算机,实现安全的远程管理

文章标题 简介一&#xff0c;参数列表二&#xff0c;使用介绍1. 连接远程服务器2. 使用SSH密钥登录2.1 生成密钥对2.2 将公钥复制到远程服务器 3. 端口转发3.1 本地端口转发3.2 远程端口转发 4. X11转发5. 文件传输与远程命令执行5.1 文件传输5.1.1 从本地向远程传输文件5.1.2 …

vue使用jsplumb 流程图

安装jsPlumb库&#xff1a;在Vue项目中使用npm或yarn安装jsPlumb库。 npm install jsplumb 创建一个Vue组件&#xff1a;创建一个Vue组件来容纳jsPlumb的功能和呈现。 <template><div style"margin: 20px"><div style"margin: 20px">&l…

图数据库_Neo4j和SpringBoot整合使用_创建节点_删除节点_创建关系_使用CQL操作图谱---Neo4j图数据库工作笔记0009

首先需要引入依赖 springboot提供了一个spring data neo4j来操作 neo4j 可以看到它的架构 这个是下载下来的jar包来看看 有很多cypher对吧 可以看到就是通过封装的驱动来操作graph database 然后开始弄一下 首先添加依赖

Python爬虫性能优化:多进程协程提速实践指南

各位大佬们我又回来了&#xff0c;今天我们来聊聊如何通过多进程和协程来优化Python爬虫的性能&#xff0c;让我们的爬虫程序6到飞起&#xff01;我将会提供一些实用的解决方案&#xff0c;让你的爬虫速度提升到新的高度&#xff01; 1、多进程提速 首先&#xff0c;让我们来看…

视频汇聚集中存储EasyCVR平台调用iframe地址视频无法播放,该如何解决?

安防监控视频汇聚平台EasyCVR基于云边端一体化架构&#xff0c;具有强大的数据接入、处理及分发能力&#xff0c;可提供视频监控直播、云端录像、视频云存储、视频集中存储、视频存储磁盘阵列、录像检索与回看、智能告警、平台级联、云台控制、语音对讲、AI算法中台智能分析无缝…

Java算法_ 检查对称树(LeetCode_Hot100)

题目描述&#xff1a;给你一个二叉树的根节点 &#xff0c; 检查它是否轴对称。root 获得更多&#xff1f;算法思路:代码文档&#xff0c;算法解析的私得。 运行效果 完整代码 /*** 2 * Author: LJJ* 3 * Date: 2023/8/17 8:47* 4*/ public class SymmetricTree {static class…

C语言入门_Day 6布尔数与比较运算

目录 前言 1.布尔数 2.比较运算 3.易错点 4.思维导图 前言 除了算术计算以外&#xff0c;编程语言中还会大量使用比较运算&#xff0c;并会根据比较运算的结果是“真”还是“假”&#xff0c;来执行不同的代码。 当你想买一杯奶茶&#xff0c;准备支付的时候&#xff0c;支…

VisualStudio打包项目文件为.exe安装包

前言&#xff1a; 使用扩展&#xff1a;install Projects 注意事项&#xff1a;打包项目前&#xff0c;确保项目能正常运行&#xff0c;不然打包毫无意义。 一、安装扩展 打开vs软件->扩展->管理扩展->搜索install Projects->安装->重启软件 二、制作安装包&a…