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,然后选择要创建minidum 还是 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文件导出,方便后续查找文件

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. 通过 【工具->选项->调试->符号】设置符号文件路径。

 3. 点击右上角的 【使用 混合 进行调试】,则可以查看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.mzph.cn/news/41345.shtml

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

相关文章

go_并发编程(1)

go并发编程 一、 并发介绍1&#xff0c;进程和线程2&#xff0c;并发和并行3&#xff0c;协程和线程4&#xff0c;goroutine 二、 Goroutine1&#xff0c;使用goroutine1&#xff09;启动单个goroutine2&#xff09;启动多个goroutine 2&#xff0c;goroutine与线程3&#xff0…

在 React 中获取数据的6种方法

一、前言 数据获取是任何 react 应用程序的核心方面。对于 React 开发人员来说&#xff0c;了解不同的数据获取方法以及哪些用例最适合他们很重要。 但首先&#xff0c;让我们了解 JavaScript Promises。 简而言之&#xff0c;promise 是一个 JavaScript 对象&#xff0c;它将…

排序+运算>直接运算的效率的原因分析

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

ADIS16470和ADIS16500从到手到读出完整数据,附例程

由于保密原因&#xff0c;不能上传我这边的代码&#xff0c;我所用的开发环境是IAR&#xff0c; 下边转载别的博主的文章&#xff0c;他用的是MDK 下文的博主给了你一个很好的思路&#xff0c;特此提出表扬 最下方是我做的一些手册批注&#xff0c;方便大家了解这个东西 原文链…

如何利用 ChatGPT 进行自动数据清理和预处理

推荐&#xff1a;使用 NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 ChatGPT 已经成为一把可用于多种应用的瑞士军刀&#xff0c;并且有大量的空间将 ChatGPT 集成到数据科学工作流程中。 如果您曾经在真实数据集上训练过机器学习模型&#xff0c;您就会知道数据清理和预…

novnc 和 vnc server 如何实现通信?原理?

参考&#xff1a;https://www.codenong.com/js0f3b351a156c/

随机微分方程

应用随机过程|第7章 随机微分方程 见知乎&#xff1a;https://zhuanlan.zhihu.com/p/348366892?utm_sourceqq&utm_mediumsocial&utm_oi1315073218793488384

复习3-5天【80天学习完《深入理解计算机系统》】第七天

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

Linux与bash(基础内容一)

一、常见的linux命令&#xff1a; 1、文件&#xff1a; &#xff08;1&#xff09;常见的文件命令&#xff1a; &#xff08;2&#xff09;文件属性&#xff1a; &#xff08;3&#xff09;修改文件属性&#xff1a; 查看文件的属性&#xff1a; ls -l 查看文件的属性 ls …

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows 摘要当前的检测sota模型网络架构swin Transformer和Vision Transformer的不同之处整体架构Patch Partition结构Linear Embedding结构Swin Transformer Block结构 Patch MergingW-MSAMSA模块计算量W-M…

Genoss GPT简介:使用 Genoss 模型网关实现多个LLM模型的快速切换与集成

一、前言 生成式人工智能领域的发展继续加速&#xff0c;大型语言模型 (LLM) 的用途范围不断扩大。这些用途跨越不同的领域&#xff0c;包括个人助理、文档检索以及图像和文本生成。ChatGPT 等突破性应用程序为公司进入该领域并开始使用这项技术进行构建铺平了道路。 大公司正…

如何发布自己的小程序

小程序的基础内容组件 text&#xff1a; 文本支持长按选中的效果 <text selectable>151535313511</text> rich-text: 把HTML字符串渲染为对应的UI <rich-text nodes"<h1 stylecolor:red;>123</h1>"></rich-text> 小程序的…

MySql过滤重复数据

假设模型表是: 1. 根据单字段过滤: SELECT user_name, COUNT(*) as count FROM sys_user GROUP BY user_name HAVING count > 1;结果: 2. 根据多个字段查询重复数据 SELECT user_name, email, COUNT(*) as count FROM sys_user GROUP BY user_name, email HAVING count…

[centos]设置主机名

1、设置 hostnamectl set-hostname 名字 2、查看是否生效 hostnamectl status 3、打开一个新链接就可以了

[python] 使用Jieba工具中文分词及文本聚类概念

前面讲述了很多关于Python爬取本体Ontology、消息盒InfoBox、虎扑图片等例子&#xff0c;同时讲述了VSM向量空间模型的应用。但是由于InfoBox没有前后文和语义概念&#xff0c;所以效果不是很好&#xff0c;这篇文章主要是爬取百度5A景区摘要信息&#xff0c;再利用Jieba分词工…

hive--给表名和字段加注释

1.建表添加注释 CREATE EXTERNAL TABLE test(loc_province string comment 省份,loc_city string comment 城市,loc_district string comment 区,loc_street string comment 街道,)COMMENT 每日数据处理后的表 PARTITIONED BY (par_dt string) ROW FORMAT SERDEorg.apache.had…

71 # 协商缓存的配置:通过内容

对比&#xff08;协商&#xff09;缓存 比较一下再去决定是用缓存还是重新获取数据&#xff0c;这样会减少网络请求&#xff0c;提高性能。 对比缓存的工作原理 客户端第一次请求服务器的时候&#xff0c;服务器会把数据进行缓存&#xff0c;同时会生成一个缓存标识符&#…

Transformer是什么,Transformer应用

目录 Transformer应用 Transformer是什么 Transformer应用:循环神经网络 语言翻译:注重语句前后顺序 RNN看中单个特征; CNN:看中特征之间时序性 模型关注不同位置的能力 Transformer是什么 Transformer是一个利用注意力机制来提高模型训练速度的模型。关于注意力机…

whisper语音识别部署及WER评价

1.whisper部署 详细过程可以参照&#xff1a;&#x1f3e0; 创建项目文件夹 mkdir whisper cd whisper conda创建虚拟环境 conda create -n py310 python3.10 -c conda-forge -y 安装pytorch pip install --pre torch torchvision torchaudio --extra-index-url 下载whisper p…

智慧工地云平台源码——塔机监控系统

智慧工地概念 智慧工地是一种崭新的工程全生命周期管理理念&#xff0c;是指运用信息化手段&#xff0c;通过对工程项目进行精确设计和施工模拟&#xff0c;围绕施工过程管理&#xff0c;建立互联协同、智能生产、科学管理的施工项目信息化生态圈&#xff0c;并将此数据在虚拟…