在程序崩溃时,需要对异常的情况进行捕获,并捕获到的堆栈信息保持下来。Windows操作系统提供了一个API函数可以在程序crash之前有机会处理这些异常,就是 SetUnhandleExceptionFilter函数。(C++也有一个类似函数set_terminate可以处理未被捕获的C++异常。)

一、函数介绍:

1、SetUnhandleExceptionFilter函数的定义如下:

SetUnhandledExceptionFilter(_In_opt_ 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;typedef struct _EXCEPTION_POINTERS {PEXCEPTION_RECORD ExceptionRecord;PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

所以定义一个lpTopLevelExceptionFilter函数去处理异常。而lpTopLevelExceptionFilter函数的参数类型是*PEXCEPTION_POINTERS。

2、另一个API函数是写生成dump文件的函数MiniDumpWriteDump,该函数定义如下:

BOOL
WINAPI
MiniDumpWriteDump(_In_ HANDLE hProcess,_In_ DWORD ProcessId,_In_ HANDLE hFile,_In_ MINIDUMP_TYPE DumpType,_In_opt_ PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,_In_opt_ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,_In_opt_ PMINIDUMP_CALLBACK_INFORMATION CallbackParam);

第四个参数MINIDUMP_TYPE是转存奔溃信息的枚举类型,不同的枚举值保存奔溃信息范围不同,带来的影响就是dump文件的大小。MINIDUMP_TYPE的定义如下:

typedef enum _MINIDUMP_TYPE {MiniDumpNormal                         = 0x00000000,MiniDumpWithDataSegs                   = 0x00000001,MiniDumpWithFullMemory                 = 0x00000002,MiniDumpWithHandleData                 = 0x00000004,MiniDumpFilterMemory                   = 0x00000008,MiniDumpScanMemory                     = 0x00000010,MiniDumpWithUnloadedModules            = 0x00000020,MiniDumpWithIndirectlyReferencedMemory = 0x00000040,MiniDumpFilterModulePaths              = 0x00000080,MiniDumpWithProcessThreadData          = 0x00000100,MiniDumpWithPrivateReadWriteMemory     = 0x00000200,MiniDumpWithoutOptionalData            = 0x00000400,MiniDumpWithFullMemoryInfo             = 0x00000800,MiniDumpWithThreadInfo                 = 0x00001000,MiniDumpWithCodeSegs                   = 0x00002000,MiniDumpWithoutAuxiliaryState          = 0x00004000,MiniDumpWithFullAuxiliaryState         = 0x00008000,MiniDumpWithPrivateWriteCopyMemory     = 0x00010000,MiniDumpIgnoreInaccessibleMemory       = 0x00020000,MiniDumpWithTokenInformation           = 0x00040000,MiniDumpWithModuleHeaders              = 0x00080000,MiniDumpFilterTriage                   = 0x00100000,MiniDumpWithAvxXStateContext           = 0x00200000,MiniDumpWithIptTrace                   = 0x00400000,MiniDumpValidTypeFlags                 = 0x007fffff,
} MINIDUMP_TYPE;

关于上面枚举值对应保存数据范围的介绍可参考MINIDUMP_TYPE详解_神知道下一秒会发生什么的博客-CSDN博客_minidump_type

下面介绍部分枚举值:

MiniDumpNormal

常选值,该类型仅包含捕获进程中所有线程的堆栈跟踪的必要信息。

MiniDumpWithDataSegs
    包含来自所有加载模块中的可写数据段,此选项会使minidump文件显著增大,对每个模块的控制使用了MODULE_WRITE_FLAGS枚举类型的ModuleWriteDataSeg枚举值。如果我们希望查看全局变来那个值,但有不想使用MiniDumpWithFullMemory,可以使用此选项。

MiniDumpWithFullMemory
      包含进程中所有可以访问的内存信息,原始内存信息包含在文件的末端,所以不用原始内存信息可以直接映射数据结构。但是该选项会造成minidump文件非常巨大。
使用该选项可以查看存储在栈上、堆上、模块数据段的所有数据。甚至还可以看到线程和进程环境块(Process Environment Block和Thread Environment Bolck, PEB和TEB)的数据。这些没有公开的数据结构可以给我们的调试提供无价的帮助。

MiniDumpWithHandleData
    包含生成dump文件时活跃的系统句柄的高级别信息。
使用该选项minidump会包括故障时刻进程故障表里面的所有句柄。可以用WinDbg的!handle来显示这些信息。

MiniDumpFilterMemory
    栈内存的内容会在保存到minidump前被过滤,除了重建栈跟踪所必须的指针,其他都会被用0数据覆盖。即调用栈可以被重建,但是所有局部变量和函数参数的值都是0。此选项只影响线程栈占用内存的内容。其他内存(比如堆)不受影响。如果使用了MiniDumpWithFullMemory,这个标志就不起作用了。

第五个参数定义如下:

typedef struct _MINIDUMP_EXCEPTION_INFORMATION {DWORD ThreadId;PEXCEPTION_POINTERS ExceptionPointers;BOOL ClientPointers;
} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;

上述PEXCEPTION_POINTERS 为异常捕获指针。

二、demo如下:

//创建dmp文件头文件.h
#pragma once
#include <string>
#include <memory>
using namespace std;
class CCreateDump
{
public:CCreateDump();~CCreateDump(void);static CCreateDump* Instance();static long __stdcall UnhandleExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo);//声明Dump文件,异常时会自动生成。会自动加入.dmp文件名后缀void DeclarDumpFile(std::string dmpFileName = "");
private:static std::string                  m_strDumpFile;static shared_ptr<CCreateDump*>    m_sptrInstance;
};/
创建dmp的.cpp文件
#include <Windows.h>
#include "CListenDump.h"
#include <DbgHelp.h>
#pragma comment(lib,  "dbghelp.lib")std::shared_ptr<CCreateDump*>  CCreateDump::m_sptrInstance = make_shared<CCreateDump*>();
std::string CCreateDump::m_strDumpFile = "";CCreateDump::CCreateDump()
{
}CCreateDump::~CCreateDump(void)
{}long  CCreateDump::UnhandleExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo)
{HANDLE hFile = CreateFile(m_strDumpFile.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile != INVALID_HANDLE_VALUE){MINIDUMP_EXCEPTION_INFORMATION   ExInfo;ExInfo.ThreadId = ::GetCurrentThreadId();ExInfo.ExceptionPointers = ExceptionInfo;ExInfo.ClientPointers = FALSE;//   write   the   dumpBOOL   bOK = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL);CloseHandle(hFile);if (!bOK){DWORD dw = GetLastError();//写dump文件出错处理,异常交给windows处理return EXCEPTION_CONTINUE_SEARCH;}else{    //在异常处结束return EXCEPTION_EXECUTE_HANDLER;}}else{return EXCEPTION_CONTINUE_SEARCH;}
}void CCreateDump::DeclarDumpFile(std::string dmpFileName)
{SYSTEMTIME syt;GetLocalTime(&syt);char szTime[MAX_PATH];sprintf_s(szTime, MAX_PATH, "[%04d-%02d-%02dT%02d-%02d-%02d]", syt.wYear, syt.wMonth, syt.wDay, syt.wHour, syt.wMinute, syt.wSecond);m_strDumpFile = dmpFileName + std::string(szTime);m_strDumpFile += std::string(".dmp");SetUnhandledExceptionFilter(UnhandleExceptionFilter);
}CCreateDump* CCreateDump::Instance()
{if (*m_sptrInstance == NULL){m_sptrInstance = make_shared<CCreateDump*>(new CCreateDump);}return *m_sptrInstance;
}//主函数cpp文件如下:
// CreateDump.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include <iostream>
#include "CListenDump.h"
#include<windows.h>
#include<stdio.h>
int main()
{char szPath[512] = { 0 };//查找可执行文件路径,将dump文件写入可执行文件路径下GetModuleFileName(NULL, szPath, sizeof(szPath) - 1);printf("path:%s\n", szPath);std::string strFilePathTmp = szPath;std::string strDumPath = "";if (strFilePathTmp.rfind(".exe") != string::npos){int nIndex = strFilePathTmp.rfind("\\");if (nIndex != -1){strDumPath = strFilePathTmp.substr(0,nIndex+1);}}strDumPath = strDumPath + "dumpfile";CCreateDump::Instance()->DeclarDumpFile(strDumPath);int nSub = 0;int nValue = 10 / nSub;std::cout << "Hello World!\n";return 0;
}

上述产生dmp文件程序编写参考于Dump文件的生成和使用_不当初-CSDN博客_dump文件

三、调试dmp文件如下:

上述demo运行产生的dmp文件使用VS打开,本文工具使用VS2017,

(1)设置pdb路径

pdb路径如红笔所示

(2)设置源代码路径:

(3)点击运行

调试结果如下:

VS生成dump文件和调试dump文件相关推荐

  1. vscode调试html文件,vscode调试html文件

    1. vscode调试html文件 主要说明使用使用Debugger for Chrome插件如何配置,以及Nodejs的方式调试. 本文的配置方式是基于deepin系统的,适用于所有debian系的 ...

  2. 020 Android之so文件动态调试

    文章目录 ELF文件格式查看工具 so文件加载时的函数执行顺序 so文件动态调试 so文件调试技巧 使用ida动态调试的那些坑 进程显示不全 illegal segment bitness more ...

  3. VS2015调试dump文件时提示未找到xxx.exe或xxx.dll

    前言 游戏开发的过程中,经常会出现客户端宕机的问题,这时候一个小小的dump文件可以记录当时的内存及堆栈情况,对于解决崩溃的问题有巨大的帮助,之前用VS2008的时候调试过dump文件,但是最近客户端 ...

  4. 无法查找或打开 pdb 文件。_Crash Dump调试:Symbol Server/Source Server、PDB原理分析

    背景 UE4引擎时不时要魔改编译.可能大一点的项目是难以避免的吧 ┓( ´∀` )┏ 工程C++会自动编译,有持续集成平台做统一的编译和分发.这样可以不用每个人都编译引擎和工程C++了,代码安全性和开 ...

  5. 自定义VS程序异常处理及调试Dump文件(一)

    1. Dump文件 1. Dump文件介绍 Dump文件(Dump File),也叫转储文件,以.DMP为文件后缀.dump文件是进程在内存中的镜像文件,通过转换然后存储成以.DMP后缀的文件.dum ...

  6. Linux环境崩溃生成core文件以及调试

    Windows环境崩溃问题可根据vs调试工具查看,Linux同样可以查看调用堆栈的信息,只是 需要更改Linux设置,使程序崩溃时候产生core文件.然后gdb调试即可. 1产生core文件方法 产生 ...

  7. coredump文件的生成以及如何调试coredump文件?

    生成coredump文件的相关配置 1. 首先通过 ulimit -a 命令,查看是否允许coredump文件生成; 如下图所示,core文件大小限制为0,即:不允许core文件生成 2. 使用 ul ...

  8. linux怎么还原bak文件,Linux restore命令:还原dump操作备份下的文件、目录或分区...

    restore 命令是 dump 命令的配套命令,dump 命令是用来备份分区和数据的,而 restore 命令是用来恢复数据的. restore 命令的基本格式如下: [root@localhost ...

  9. 从java进程里dump出类的class文件的小工具--dumpclass

    Serviceability Agent 想要查看一些被增强过的类的字节码,或者一些AOP框架的生成类,就需要dump出运行时的java进程里的字节码. 从运行的java进程里dump出运行中的类的c ...

  10. linux怎么还原bak文件,Linux系统restore命令:还原dump操作备份下的文件、目录或分区...

    restore命令是dump命令的配套命令,dump命令是用来备份分区和数据的,而restore命令是用来恢复数据的. restore命令的基本格式如下:[root@localhost ~]# res ...

最新文章

  1. QTexe软件设置系统默认的图标
  2. (chap7 确保WEB安全的HTTPS) HTTPS加密
  3. 如何在 C# 中使用 FTP 上传文件
  4. 不止命令行!自定义VS生成事件
  5. 机器学习 | 早期停止法原理及Python实现
  6. Vs2010架构设计-层图(Layer Diagram)
  7. 洛谷——P1176 路径计数2
  8. 目标检测(三)--DPM
  9. 00套经典机械结构设计非标自动化SW机构3D图纸solidWorks模型库
  10. linux 如何添加字体
  11. v-charts使用-实例
  12. 百度应用开放平台简介
  13. windows下choco 安装helm
  14. MMDetection——GPU训练
  15. python scatter参数详解_Python中scatter函数参数及用法详解
  16. vue子元素点击事件与父元素点击事件冲突 子元素点击事件不触发
  17. 已解决:GET http://localhost:8080/statics/js/jquery-3.4.1.js net::ERR_ABORTED 404
  18. element el-transfer穿梭框的使用,自定义穿梭框的数据项
  19. 网络——传输层(详细版)
  20. DB2的HADR的搭建

热门文章

  1. [UESTC SC T1] 最大疯子树
  2. mysql5.1查询分析语句_MySQL 查询数据_mysql 查询语句_SELECT语句
  3. linux远程配置ssh服务,Linux远程服务之OpenSSH配置
  4. public 函数_C++:11友元函数、友元类
  5. java向数据库添加中文乱码_java向数据库中插入中文出现乱码
  6. CDATA不支持html,我应该在HTML5中使用(Should I use in HTML5?)
  7. node.val java_LeetCode——21. 合并两个有序链表(Java)
  8. 小菜找实习——阿里3.25场笔试第一题(矩阵数组最小差值和)
  9. java中spring的注解_Java代码中spring注解浅析
  10. 保活 进程唤醒_Android 8.0以上系统应用如何保活