(Windbg调试一)minidump崩溃捕捉

news/2024/2/28 16:55:49

(Windbg调试一)minidump崩溃捕捉

  • 一,系统的异常处理顺序
  • 二,SetUnhandleExceptionFilter函数
  • 三,Minidump
  • 四,代码演示
  • 五,windbg生成Dump

     在日常工作中,本地c++代码发生崩溃时,编译器都可以帮我们捕捉到并且定位到具体的代码,这是因为编译器接收到了操作系统发送过来的程序异常通知并进行了处理。但是在使用我们软件的用户环境上,没有编译器帮我们处理这个异常,操作系统会使用它的异常处理机制:弹出程序异常对话框。因此我们需要将崩溃时产生的堆栈信息生成dump文件,传送到我们的服务器上,通过Windbg工具或者vs编译器进行崩溃分析。

一,系统的异常处理顺序

1,系统首先判断异常是否应发送给目标程序的异常处理模块,如果决定应该发送,并且目标程序正在被调试,则系统挂起程序并向调试器发送EXCEPTION_DEBUG_EVENT消息。

2,如果目标程序没有被调试或者调试器未能处理异常,系统就会继续查找你是否添加了线程相关的异常处理机制,如果有,系统就把异常发送给你的程序seh处理例程,交由其处理。

3,每个线程相关的异常处理例程可以处理或者不处理这个异常,如果不处理并且安装了多个线程相关的异常处理例程,,可交由链起来的其他例程处理.。

4,如果这些例程均选择不处理异常,如果程序处于被调试状态,操作系统仍会再次挂起程序通知调试器。

5,如果程序未处于被调试状态或者调试器没有能够处理,并且程序调用SetUnhandledExceptionFilter安装了异常捕捉的话,系统转向调用它的全局异常过滤函数。

6,在调用了SetUnhandledExceptionFilter后,UnhandledExceptionFilter依旧会首先检查当前应用程序是否在调试器的控制之下,如果是,它将返回EXCEPTION_CONTINUE_SEARCH,由调试器处理当前异常。

7.,如果程序也没有调用SetUnhandledExceptionFilter,系统会调用默认的系统处理程序,通常显示一个对话框,“程序无响应”或者“程序中断”,在安装了开发环境的机器上,还会弹出附加调试的对话框,如果没有调试器能被附加于其上或者调试器也处理不了,系统 就调用ExitProcess终结程序.。

而我们程序中需要加入的崩溃捕捉模块也就是通过SetUnhandledExceptionFilter函数来实现的。

二,SetUnhandleExceptionFilter函数

     Windows操作系统提供了一个API函数可以在程序crash之前有机会处理这些异常,就是 SetUnhandleExceptionFilter函数。(C++也有一个类似函数set_terminate可以处理未被捕获的C++异常。)
SetUnhandleExceptionFilter函数声明如下:

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(__in          LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);

其中 LPTOP_LEVEL_EXCEPTION_FILTER 定义如下:

 typedef LONG (WINAPI *PTOP_LEVEL_EXCEPTION_FILTER)(__in struct _EXCEPTION_POINTERS *ExceptionInfo);typedef PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER;

     简单来说,SetUnhandleExceptionFilter允许我们设置一个自己的函数作为全局SEH过滤函数,当程序crash前会调用我们的函 数进行处理。我们可以利用的是 _EXCEPTION_POINTERS 结构类型的变量ExceptionInfo,它包含了对异常的描述以及发生异常的线程状态,过滤函数可以通过返回不同的值来让系统继续运行或退出应用程序。

三,Minidump

     minidump(小存储器转储)可以理解为一个dump文件,里面记录了能够帮助调试crash的最小有用信息。实际上,如果你在 系统属性 -> 高级 -> 启动和故障恢复 -> 设置 -> 写入调试信息 中选择“小内存转储(64 KB)”的话,当系统意外停止时都会在C:\Windows\Minidump\路径下生成一个.dmp后缀的文件,这个文件就是minidump文件。
在这里插入图片描述

      只不过这种方式生成的是内核态的minidump。我们要生成的是用户态的minidump,文件中包含了程序运行的模块信息、线程信息、堆栈调用信息等。而且为了符合其mini的特性,dump文件是压缩过的。

     windows操作系统也给我们提供了一个API函数可以来写minidump信息,就是MiniDumpWriteDump函数,函数声明如下:

BOOL
WINAPI
MiniDumpWriteDump(IN HANDLE hProcess,	//当前进程句柄IN DWORD ProcessId, //当前进程IDIN HANDLE hFile,	//文件句柄IN MINIDUMP_TYPE DumpType,	//MINIDUMP类型IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL	//异常信息(最重要)IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL //用户数据流(一般不需要)IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL		//回调(一般不需要));

     ExceptionParam是最关键的参数,它是一个PMINIDUMP_EXCEPTION_INFORMATION 结构体,结构体内部有一个PEXCEPTION_POINTERS成员,也就是上面PTOP_LEVEL_EXCEPTION_FILTER函数指针的参数。

四,代码演示

     dump捕捉分为进程内和进程外两种,一般都认为进程内进行dump捕捉是不安全的,因为程序已经异常了,在异常的堆或栈上进行操作是有风险的,会导致二次异常。因此在实际的项目中都会采用进程外捕捉dump,两个进行通过共享内存来共享PEXCEPTION_POINTERS异常指针,由异常捕捉进行来写dump文件,并上传到我们自己的服务器上。具体用哪种方式,我觉得视程序的使用场景来定,下面贴上封装好了的dump_catch.h文件的代码,只有一个文件,调用方式很简单,在程序的入口函数最上方调用::SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);即可,默认在exe同级目录下的dump文件夹下生成minidump文件(日期命名).

/*created:	2018/12/25filename:	dump.hauthor:		libingdepend:		dbghelp.lib,Dbghelp.hbuild:		vc(windows)spurpose:	实现windows程序崩溃捕捉,落地成dump文件.没有封装成类,是因为没有必要,都是几个简单的静态函数,写在一个.h文件中,也方便调用。useway:		在main函数或者WinMain函数中,程序初始化之前调用::SetUnhandledExceptionFilter(UnhandledExceptionFilterEx)即可。
*/#pragma once
#include "Dbghelp.h"
#include <shlwapi.h>#pragma comment(lib, "Dbghelp.lib")
#pragma comment(lib, "shlwapi.lib")BOOL CALLBACK MiniDumpCallback(PVOID, const PMINIDUMP_CALLBACK_INPUT input, PMINIDUMP_CALLBACK_OUTPUT output)
{if (input == NULL || output == NULL)return FALSE;BOOL ret = FALSE;switch (input->CallbackType){case IncludeModuleCallback:case IncludeThreadCallback:case ThreadCallback:case ThreadExCallback:ret = TRUE;break;case ModuleCallback:{if (!(output->ModuleWriteFlags & ModuleReferencedByMemory)){output->ModuleWriteFlags &= ~ModuleWriteModule;}ret = TRUE;}break;default:break;}return ret;
}void WriteDump(EXCEPTION_POINTERS* exp, const std::string &path)
{HANDLE h = ::CreateFile(path.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);if(h == InvalidHandle){//AfxMessageBox("HANDLE h = ::CreateFile");//这里可以加日志return;}MINIDUMP_EXCEPTION_INFORMATION info;info.ThreadId = ::GetCurrentThreadId();info.ExceptionPointers = exp;info.ClientPointers = NULL;MINIDUMP_CALLBACK_INFORMATION mci;mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;mci.CallbackParam = 0;MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory);MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h, mdt, &info, NULL, &mci);::CloseHandle(h);
}void GetDirPath(std::string & strDir)
{//dump文件存储路径,存储在exe同级目录下的Dump文件夹中char szAppPath[MAX_PATH] = { 0 };GetModuleFileName(NULL, szAppPath, sizeof(szAppPath) - 1);(strrchr(szAppPath, '\\'))[0] = 0;strDir = szAppPath;strDir.append("\\Dump");if(!PathFileExists(strDir.c_str())){CreateDirectory(strDir.c_str(), NULL);}strDir.append("\\");
}LONG WINAPI UnhandledExceptionFilterEx(EXCEPTION_POINTERS* exp)
{SYSTEMTIME szSysDate;GetLocalTime(&szSysDate);char szFileName[MAX_PATH] = {0};sprintf(szFileName, "%04d%02d%02d_%02d%02d%02d.dmp",szSysDate.wYear, szSysDate.wMonth, szSysDate.wDay, szSysDate.wHour, szSysDate.wMinute, szSysDate.wSecond);std::string dir;GetDirPath(dir);dir.append(szFileName);WriteDump(exp, dir);char szBuf[512] = {0};sprintf(szBuf, "程序崩溃, dump文件为:%s", dir.c_str());//可以做点别的return EXCEPTION_EXECUTE_HANDLER;
}

五,windbg生成Dump

当我们通过windbg调试进程时(Attach Process),如果程序崩溃了,可以通过windbg的.dump命令,选择不同的参数来生成不同类型的dump文件。

  • .dump /m C:/dumps/myapp.dmp
    缺省选项,生成标准的minidump, 转储文件通常较小,便于在网络上通过邮件或其他方式传输。 这种文件的信息量较少,只包含系统信息、加载的模块(DLL)信息、 进程信息和线程信息。
  • .dump /ma C:/dumps/myapp.dmp
    带有尽量多选项的minidump(包括完整的内存内容、句柄、未加载的模块,等等),文件很大,但如果条件允许(本机调试,局域网环境), 推荐使用这种dump。
  • .dump /mFhutwd C:/dumps/myapp.dmp
    带有数据段、非共享的读/写内存页和其他有用的信息的minidump。包含了通过minidump能够得到的最多的信息。是一种折中方案。

参考资料:
1,https://www.cnblogs.com/lidabo/p/3635960.html
2,<windows核心编程>第25章


http://www.ppmy.cn/news/574808.html

相关文章

异常处理与MiniDump详解 4 MiniDump

分享一下我老师大神的人工智能教程&#xff01;零基础&#xff0c;通俗易懂&#xff01;http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章。分享知识&#xff0c;造福人民&#xff0c;实现我们中华民族伟大复兴&#xff01; 异常处理与MiniDump详解(4) MiniDump writ…

自己创建 minidump

以前曾写过一个 bugslayer.dll 的介绍. 在程序出错时将调用栈写到文件. 觉得不错. 后来开始用 windbg. 知道了 userdump. 知道了如何调试 dump... 才知道程序崩溃的时候写 dump 文件其实可以获取比调用栈多得多的信息. 如果你的程序什么都不干. 那么在程序出错的时候. drwts…

MiniDump不生成或者生成0字节

今天在使用C写一个Windows多线程程序时&#xff0c;发现退出过程中有段错误&#xff0c;为了方便快速的定位问题&#xff0c;我使用了MiniDump。 MiniDump.c源码如下&#xff1a; #include <stdio.h> #include <stdlib.h> #include <time.h> #include <…

MiniDump文件的生成(一)

使用DbgHelp提供的MiniDumpWriteDump函数可以在程序崩溃的时候产生包含足够多信息的MiniDump文件供调试程序使用。 1. MiniDumpWriteDump的声明如下 详见: http://msdn.microsoft.com/en-us/library/windows/desktop/ms680360(vvs.85).aspx 2. 作为示例&#xff0c;下面…

用windbg分析蓝屏文件minidump随记!!

用windbg分析蓝屏文件minidump&#xff0c;以解决加载驱动蓝屏的相关问题随记。 案例1&#xff1a;能够正常进入操作系统&#xff0c;按照如下提示设置: a. 右击“我的电脑”选择“属性”; b. 在弹出的对话框中选择 “高级”&#xff0d;> “设置”; c.“自动重新启动…

MINIDUMP_TYPE详解

MINIDUMP_TYPE 枚举类型详解 一、MINIDUMP_TYPE 的作用 相信大家都知道我们可以使用minidump文件来记录Windows程序崩溃时的信息&#xff0c;其是一种内存转储&#xff0c;其第一代原型是一种“全用户转储&#xff08;Full User Dump&#xff09;”,里面包含了全部的进程内存信…

【小沐学C++】C++ 捕获程序异常奔溃minidump

文章目录 1、简介1.1 MiniDumpWriteDump函数1.2 Visual Studio分析小型转储1.3 使用 Microsoft 公共符号服务器1.4 使用 WinDbg 调试小型转储 2、代码实现2.1 例子一2.2 例子二2.3 例子三2.4 例子四2.5 其他例子 3、调试工具3.1 windbg3.2 debugdiag3.3 Visual Studio 结语 1、…

Minidump方式保留程序崩溃现场

介绍部分转自https://www.cnblogs.com/lisuyun/p/5245609.html 程序部分为原创。 Minidump方式保留程序崩溃现场 在Windows平台下用C开发应用程序&#xff0c;最不想见到的情况恐怕就是程序崩溃&#xff0c;而要想解决引起问题的bug&#xff0c;最困难的应该就是调试release版…

MiniDump文件的生成(二)

在《MiniDump文件生成&#xff08;一&#xff09;》中简单的介绍了一下怎样在程序崩溃的时候生成供调试使用的DMP文件&#xff0c;本文将详细的介绍一下MINIDUMP_TYPE中的每一种类型以及针对每一种类型所生成的DMP文件中将包含哪些特定信息。 首先来看一下&#xff0c;Windows…

写入的dump文件为0kb (1、MiniDumpWriteDump 简单理解)

1、了解下MiniDumpWriteDump MiniDumpWriteDump (vs2008) MSDN ImageHlp.h 文件 // …… 4647-4657BOOL WINAPI MiniDumpWriteDump(IN HANDLE hProcess,IN DWORD ProcessId,IN HANDLE hFile,IN MINIDUMP_TYPE DumpType,IN CONST PMINIDUMP_EXCEPTION_INFORMATION Excepti…

处理minidump文件用到的“工具”的分享

前言 最近崩溃平台有BUG&#xff0c;native的崩溃堆栈解析不出来&#xff0c;只能自己线下人肉解堆栈了。本着能善用工具提高工作效果的习惯&#xff0c;最终收获了如下的zshe脚本&#xff08;方法&#xff09;用于后续的工作&#xff0c;借此笔记跟大家分享与交流&#xff0c…

简单分析minidump

转载自&#xff1a;http://91dengdeng.cn/2019/05/07/%E7%AE%80%E5%8D%95%E5%88%86%E6%9E%90minidump-1/ 简单分析minidump(1) 有了前几节的准备工作&#xff0c;我们的程序已经可以自动捕获异常了&#xff0c;那么我们开始通过windbg来分析dump解决实际问题。先从简单入手&am…

Minidump 文件分析工具

Minidump 文件分析工具 microsoft, 解决问题, 计算机, 操作系统, 存储器 许多人可能经常遇见计算机频繁重新启动的问题&#xff0c;总是难于解决问题&#xff0c;最后只能重新安装操作系统&#xff0e;我介绍的这篇文章应该能解决许多人这样的痛苦&#xff0e;   通常在荡机…

异常处理与MiniDump详解(4) MiniDump

异常处理与MiniDump详解(4) MiniDump write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 一、 综述 总算讲到MiniDump了。 Dump有多有用我都无法尽数&#xff0c;基本上属于定位错误修复BUG的倚天剑。&#xff08;日志可以算是屠龙刀&#xff09;这…

操作系统——银行家算法的模拟与实现

一&#xff1a;实验题目 银行家算法的模拟与实现 二&#xff1a;实验目的 (1) 进一步了解进程的并发执行。 (2) 加强对进程死锁的理解&#xff0c;理解安全状态与不安全状态的概念。 (3) 掌握使用银行家算法避免死锁问题。 三、总体设计&#xff08;含背景知识或基本原…

亚马逊云科技数据库市场份额提升迅速,合作伙伴和开发者生态系统为其赋能

对比常规的基础设施上云和应用上云,企业对于数据上云一直保持最为慎重的态度。不过也不是一成不变的,Gartner前不久公布的一组数据显示,在2022年全球数据库管理系统的市场份额排名中,作为纯云厂商的亚马逊云科技,超越了老牌传统数据库厂商甲骨文和微软,首次位居第一。 降低企业…

Android应用分身的实现和解析

1 背景 从去年下半年360奇酷手机发布后&#xff0c;国内的手机新品发布&#xff0c;都会提到应用分身、微信双开等类似概念&#xff0c;有一些第三方应用也以分身/双开作为亮点抢占市场&#xff0c;一时间分身类应用成为主流手机的一个必备功能。 在了解和比较了国内的分身…

Android应用分身功能介绍

作者 Steven.zhu 1 背景 从去年下半年360奇酷手机发布后&#xff0c;国内的手机新品发布&#xff0c;都会提到应用分身、微信双开等类似概念&#xff0c;有一些第三方应用也以分身/双开作为亮点抢占市场&#xff0c;一时间分身类应用成为主流手机的一个必备功能。 在了解和…

废旧手机秒变PHP服务,轻松拥有随身服务器

废旧手机秒变PHP服务&#xff0c;轻松拥有随身服务器 个人有一台360奇酷手机没有在使用&#xff0c;伊拉克成色&#xff0c;手机卡的一P食之无味弃之可惜的典范&#xff0c;于是想把这个安卓变为PHP服务器&#xff0c;并且装一个wordpress测试项目&#xff0c;说干就干。 需要…

Android 虚拟多开系列二——技术原理

目录 Android虚拟多开应用有哪些&#xff1f; Android虚拟多开应用技术原理有哪几类&#xff1f; Android虚拟多开需求分析 反虚拟多开技术 正文 一、Android虚拟多开应用列表 应用名称版本号开源公司名称下载链接太极 否维术&#xff08;个人&#xff09;微信公众号&#xff1…
最新文章