Crash -- 生成Minidump调试信息

2 篇文章 0 订阅
订阅专栏

在Windows平台下用C++开发应用程序,最不想见到的情况恐怕就是程序崩溃,而要想解决引起问题的bug,最困难的应该就是调试release版本了。因为release版本来就少了很多调试信息,更何况一般都是发布出去由用户使用,crash的现场很难保留和重现。目前有一些方法可以解决:

崩溃地址 + MAP文件;MAP文件;

SetUnhandledExceptionFilter + Minidump。


本文重点解决Minidump方式。



 1、Minidump概念
        minidump(小存储器转储)可以理解为一个dump文件,里面记录了能够帮助调试crash的最小有用信息。实际上,如果你在系统属性 -> 高级 -> 启动和故障恢复 -> 设置 -> 写入调试信息中选择“小内存转储(64 KB)”的话,当系统意外停止时都会在C:\Windows\Minidump\路径下生成一个.dmp后缀的文件,这个文件就是minidump文件,只不过这个是内核态的minidump。
        我们要生成的是用户态的minidump,文件中包含了程序运行的模块信息、线程信息、堆栈调用信息等。而且为了符合其mini的特性,dump文件是压缩过的。


2、生成minidump文件
        通过drwtsn32、NTSD、CDB等调试工具生成Dump文件, drwtsn32存在的缺点虽然NTSD、CDB可以完全解决,但并不是所有的操作系统中都安装了NTSD、CDB等调试工具。根据MiniDumpWriteDump接口,完全可以程序自动生成Dump文件。


 


3、  自动生成Minidump文件
        当程序遇到未处理异常(主要指非指针造成)导致程序崩溃死,如果在异常发生之前调用了SetUnhandledExceptionFilter()函数,异常交给函数处理。MSDN中描述为:


Issuing SetUnhandledExceptionFilter replaces the existing top-level exception filter for all existing and all future threads in the calling process.


 因而,在程序开始处增加SetUnhandledExceptionFilter()函数,并在函数中利用适当的方法生成Dump文件,即可实现需要的功能。minidump(小存储器转储)可以理解为一个dump文件,里面记录了能够帮助调试crash的最小有用信息。实际上,如果你在系统属性 -> 高级 -> 启动和故障恢复 -> 设置 -> 写入调试信息中选择“小内存转储(64 KB)”的话,当系统意外停止时都会在C:\Windows\Minidump\路径下生成一个.dmp后缀的文件,这个文件就是minidump文件,只不过这个是内核态的minidump。

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


2、生成minidump文件
通过drwtsn32、NTSD、CDB等调试工具生成Dump文件, drwtsn32存在的缺点虽然NTSD、CDB可以完全解决,但并不是所有的操作系统中都安装了NTSD、CDB等调试工具。根据MiniDumpWriteDump接口,完全可以程序自动生成Dump文件。


3、  自动生成Minidump文件
当程序遇到未处理异常(主要指非指针造成)导致程序崩溃死,如果在异常发生之前调用了SetUnhandledExceptionFilter()函数,异常交给函数处理。MSDN中描述为:

        Issuing SetUnhandledExceptionFilter replaces the existing top-level exception filter for all existing and all future threads in the calling process.

        因而,在程序开始处增加SetUnhandledExceptionFilter()函数,并在函数中利用适当的方法生成Dump文件,即可实现需要的功能。

新建工程


下一步


下一步


Minidmp.h 

#pragma once

#include <windows.h>
#include <imagehlp.h>
#include <stdlib.h>


inline BOOL IsDataSectionNeeded(const WCHAR* pModuleName);

inline BOOL CALLBACK MiniDumpCallback(PVOID pParam, const PMINIDUMP_CALLBACK_INPUT pInput, PMINIDUMP_CALLBACK_OUTPUT pOutput);

//创建Dump文件
inline void CreateMiniDump(EXCEPTION_POINTERS* pep, LPCTSTR strFileName);

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);

BOOL PreventSetUnhandledExceptionFilter();


LONG WINAPI UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS *pException);

//运行异常处理
void RunCrashHandler();

Minidmp.cpp 

#include "stdafx.h"

#include "Minidmp.h"

#pragma comment(lib, "dbghelp.lib")

inline BOOL IsDataSectionNeeded(const WCHAR* pModuleName)
{
	if(pModuleName == 0)
	{
		return FALSE;
	}

	WCHAR szFileName[_MAX_FNAME] = L"";
	_wsplitpath(pModuleName, NULL, NULL, szFileName, NULL);
	if(wcsicmp(szFileName, L"ntdll") == 0)
		return TRUE;

	return FALSE; 
}

inline BOOL CALLBACK MiniDumpCallback(PVOID                            pParam, 
	const PMINIDUMP_CALLBACK_INPUT   pInput, 
	PMINIDUMP_CALLBACK_OUTPUT        pOutput)
{
	if(pInput == 0 || pOutput == 0)
		return FALSE;

	switch(pInput->CallbackType)
	{
	case ModuleCallback: 
		if(pOutput->ModuleWriteFlags & ModuleWriteDataSeg) 

			if(!IsDataSectionNeeded(pInput->Module.FullPath)) 

				pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg); 

	case IncludeModuleCallback:
	case IncludeThreadCallback:
	case ThreadCallback:
	case ThreadExCallback:
		return TRUE;

	default:;
	}

	return FALSE;
}

//创建Dump文件
inline void CreateMiniDump(EXCEPTION_POINTERS* pep, LPCTSTR strFileName)
{
	HANDLE hFile = CreateFile(strFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
	{
		MINIDUMP_EXCEPTION_INFORMATION mdei;
		mdei.ThreadId           = GetCurrentThreadId();
		mdei.ExceptionPointers  = pep;
		mdei.ClientPointers     = FALSE;
		MINIDUMP_CALLBACK_INFORMATION mci;
		mci.CallbackRoutine     = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;
		mci.CallbackParam       = 0;
		MINIDUMP_TYPE mdt       = (MINIDUMP_TYPE)0x0000ffff;
		MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mdei, NULL, &mci);

		CloseHandle(hFile); 
	}
}

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
{
	return NULL;
}

BOOL PreventSetUnhandledExceptionFilter()
{
	HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
	if (hKernel32 ==   NULL)
		return FALSE;


	void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");
	if(pOrgEntry == NULL)
		return FALSE;


	unsigned char newJump[ 100 ];
	DWORD dwOrgEntryAddr = (DWORD) pOrgEntry;
	dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far


	void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
	DWORD dwNewEntryAddr = (DWORD) pNewFunc;
	DWORD dwRelativeAddr = dwNewEntryAddr -  dwOrgEntryAddr;


	newJump[ 0 ] = 0xE9;  // JMP absolute
	memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc));
	SIZE_T bytesWritten;
	BOOL bRet = WriteProcessMemory(GetCurrentProcess(),    pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten);
	return bRet;
}


LONG WINAPI UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS *pException)
{
	TCHAR szMbsFile[MAX_PATH] = { 0 };
	::GetModuleFileName(NULL, szMbsFile, MAX_PATH);
	TCHAR* pFind = _tcsrchr(szMbsFile, '\\');
	if(pFind)
	{
		*(pFind+1) = 0;
		_tcscat(szMbsFile, _T("CreateMiniDump.dmp"));
		CreateMiniDump(pException,szMbsFile);
	}


	// TODO: MiniDumpWriteDump
	FatalAppExit(-1,  _T("Fatal Error"));
	return EXCEPTION_CONTINUE_SEARCH;
}

//运行异常处理
void RunCrashHandler()
{
	SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);
	PreventSetUnhandledExceptionFilter();
}

CrashTest.h 

#pragma once
#include "Minidmp.h"


class CCrashTest
{
public:
	CCrashTest(void);
	~CCrashTest(void);


public:
	void Test();

private:
	void Crash();
};

CrashTest.cpp 

#include "StdAfx.h"
#include "CrashTest.h"


CCrashTest::CCrashTest(void)
{
}


CCrashTest::~CCrashTest(void)
{
}

void CCrashTest::Test()
{
	Crash();
}

void CCrashTest::Crash()
{
	// 除零,人为的使程序崩溃
	//
	int i = 13;
	int j = 0;
	//int m = i / j;
	strcpy(NULL,"adfadfg");
}


CrashMinidumpTest.cpp 

// CrashMinidumpTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "CrashTest.h"

int _tmain(int argc, _TCHAR* argv[])
{
	//设置异常处理回调函数
	RunCrashHandler();

	CCrashTest test;
	test.Test();
	getchar();
	return 0;
}

配置工程目录



下一步


下一步


下一步


下一步


让Windows下的应用程序在崩溃的时候写dump文件的代码
stone-jin
01-25 1205
#pragma once #include "shared/util.h" #include #include "util/user.h" BOOL CALLBACK MyMiniDumpCallback(PVOID, const PMINIDUMP_CALLBACK_INPUT input, PMINIDUMP_CALLBACK_OUTPUT output) { if(input == N
MiniDump - 调试问题的基础
梦里花开的博客
06-01 728
前言 这个minidump对于在windows平台上调试程序问题是十分重要的,所以有必要提一下。 之前我有一个博客说的很详细了,但是因为同事借我的账号乱下载文件,所以直接给注销了。换了一家公司以后,发现他们的程序完全没有Dump检测机制,有点不放心,然后大致搜索,回顾一番了,决定还是再记录一遍。 代码 在这里插入代码片 ...
使用 Crash 工具分析 Linux dump 文件
技术风向标
04-05 2340
前言 Linux 内核(以下简称内核)是一个不与特定进程相关的功能集合,内核的代码很难轻易的在调试器中执行和跟踪。开发者认为,内核如果发生了错误,就不应该继续运行。因此内核发生错误时,它的行为通常被设定为系统崩溃,机器重启。基于动态存储器的电气特性,机器重启后,上次错误发生时的现场会遭到破坏,这使得查找内核的错误变得异常困难。 内核社区和一些商业公司为此开发了很多种调试技术和工具,希望...
用CreateMiniDump手工生成dump文件
weixin_34050389的博客
09-14 277
void CreateMiniDump(struct _EXCEPTION_POINTERS* ExceptionInfo){ HMODULE hModule = ::LoadLibrary(".\\dbghelp.dll"); if( NULL == hModule )  return; MiniDumpWriteDump_PTR pfnMiniDumpWriteDump = (MiniDump...
【积跬步以至千里】App Crashed - WriteMiniDump
热门推荐
水亦心的博客
07-11 2万+
问题 最近电脑一直出现一个提醒: App Crashed - WriteMiniDump 比较忙没顾得上搭理他,现在可以安心解决一下了。 产生原因 问题翻译过来是: 应用程序崩溃-写入小型转储。 产生错误的软件是 也就是2345系列软件带的广告推送插件。 解决方案 1、定期清理电脑 定期使用电脑管家或者360等软件清理电脑,将这些无用的插件关闭或者删除掉。 2、2345软件设置 这个是2345系列软件的插件,经常出现在2345看图王中,2345看图王虽然好用,.
windbg调试minidump
余先桑
08-16 318
有时候异常被捕获写进minidump导致看不到真正的异常堆栈,这里做一个简单的调试记录: 先上几张图: 好了,我只想上几张图哈哈哈,最后一张一目了然,真正的异常堆栈我们已经能够看到了。 ...
Qt工程生成MiniDump文件
02-13
在Qt开发过程中,有时我们需要对程序崩溃或者异常情况进行调试,这时生成MiniDump文件就显得尤为重要。MiniDump文件包含了进程在特定时刻的内存快照,它包含堆栈信息、线程状态以及一部分进程内存,这对于定位问题...
使用MiniDump在程序里自动生成Dump 调试错误
05-21
在这个例子中,我们首先创建了一个函数`GenerateMiniDump`,它会根据传入的异常信息生成MiniDump文件。然后,在`main`函数中,我们故意引发一个异常,并在异常处理程序中调用`GenerateMiniDump`。这样,当程序崩溃时...
minidump_stackwalk工具,用于分析breadpad生成的dmp文件。
04-09
minidump_stackwalk能够解析breadpad生成的.dmp文件,展示出在崩溃时刻程序的堆栈信息,这对于调试和排查错误至关重要。 要使用minidump_stackwalk,你需要确保已经正确地获取了dmp文件。breadpad会在程序崩溃时...
易语言-易语言崩溃自动转储minidump
06-25
总的来说,这个例子展示了易语言在异常处理和调试方面的应用,利用DLL和minidump技术,使得开发者能够在程序崩溃时获取有价值的调试信息,这对于软件的优化和问题解决具有重要意义。在实际开发中,理解并熟练运用...
MiniDumpMiniDump
11-15
minidump 源码 minidump 源码 minidump 源码 minidump 源码 minidump 源码 minidump 源码 minidump 源码 minidump 源码 minidump 源码
Minidump文件
09-29
蓝屏问题上传这个文件是想请大侠帮我看看原因是什么
minidump工具
03-19
当一个程序卡住的时候,可对这个程序产生一个dump文件,有效分析程序卡死的原因
cpp-集成Breakpad来获取发生nativecrash时候的系统信息和线程堆栈信息
08-16
在服务端,你可以使用Breakpad的`minidump_stackwalk`工具,结合之前生成的符号信息,解析.dmp文件,得到详细的崩溃位置和上下文。 **注意事项** - 确保在所有目标平台上正确配置Breakpad,包括不同操作系统和CPU...
minidump详细介绍
chentao1206的专栏
03-31 3349
Effective minidump  简介 在过去几年里,崩溃转储(crash dump)成为了调试工作的一个重要部分。如果软件在客户现场或者测试实验室发生故障,最有价值的解决方式是能够创建一个故障瞬间的应用程序状态镜像,然后可以在开发者的机器上通过调试器进行分析。第一代的crash dump通常被称为“全用户转储(full user dump)”,它包含了进程的虚拟内存的全
crash调试linux dump信息
qq_42931917的博客
08-26 8289
当发生linux 内核crash时,内核依靠kexec机制在系统引导时已分配的内存的预保留部分中快速重新引导内核的新实例。这样可以使现有存储区域保持不变,以安全地将其内容复制到存储中,下文直接延时调试整个过程。 curits@curits-virtual-machine:~/Desktop/crash-master$ sudo apt install linux-crashdump [sudo] password for curits: Reading package lists... Done Buil
MiniDump
weixin_30501857的博客
06-27 877
#pragma once void RunCrashHandler(); #include "MiniDump.h" #include <windows.h> #include <imagehlp.h> #include <stdlib.h> #include <tchar.h> #pragma comment(lib,...
crash实战:手把手教你使用crash分析内核dump
最新发布
Elvis Hu的博客
12-19 2445
Kdump是Linux的一种内核崩溃捕获机制,Linux内核遇到致命错误崩溃时会触发Kdump机制将崩溃时的现场保存下来,以便后续分析和故障排查。目前市面上有很多分析Kdump的工具,例如trace32, crash tool,本文介绍crash tool在手机领域的应用,并重点介绍一些实用的技巧。然而,本文的重点并不是介绍crash tool的工作原理和基础命令,也不是为了介绍Kdump转储的原理以及其他Kdump解析工具,如果你对这些内容感兴趣,请参考本文末尾提供的参考文档。 一、为什么要用crash
写入调试信息
Gang Zhou
05-26 7964
今天在看关于 一位朋友vista声音驱动时候观察到 写入调试信息为 "核心内存转储"所以找了MS KB的内容看了看知识库内容screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor=hand; this.alt=Click here to open new window/nCT
写文章

热门文章

  • C语言必背18个经典程序 109401
  • Windows Server 2012 解决无法连接无线网络 47094
  • linux下 如何切换到root用户 42669
  • windows--bat--设置变量的方法 42576
  • Visual Stdio平台工具集以及配置 34559

分类专栏

  • DevOps CI/CD
  • C/C++基本类型的掌握 36篇
  • 编译器设置、跨语言设置、跨平台设置 14篇
  • 数据库 16篇
  • U盘/硬盘/移动硬盘专家 1篇
  • DLL相关问题 1篇
  • Maker 术语 9篇
  • 字符串的一系列操作 6篇
  • STL 3篇
  • DesignPatterns 2篇
  • XML Parser 2篇
  • MFC 15篇
  • Algorithm 8篇
  • Assembly 2篇
  • Network 4篇
  • Microsoft Office 1篇
  • 3D Max maya 1篇
  • 程序Crash 2篇
  • SourceCode Manager 4篇
  • 软件工程 2篇
  • BCGControlBar Pro for MFC 3篇
  • QT 4篇
  • windows API 开发 4篇
  • linux 15篇
  • Virtual Stdio插件参数设置 10篇
  • JavaScript 7篇
  • windows 系统配置 8篇
  • web工具配置使用说明 1篇
  • 脚本 7篇
  • 驱动开发 5篇
  • 工程配置说明 2篇
  • COM开发 5篇
  • 通信 2篇
  • boost 2篇
  • regex 1篇
  • web 2篇

最新评论

  • ubuntu 打不开商店怎么办

    2301_79581188: software没有了安装候选怎么办

  • 如何在类的外部修改类中的私有数据成员

    yy-turbo: 牛比!救了命了!

  • DlgProc对话框回调

    好你个大头鬼: 是只能配置32位编译吗?

  • 如何在类的外部修改类中的私有数据成员

    X-WB: 谢谢大神,作业完成

  • 函数的返回竟然能作为左值

    大屁孩的春天: 米奇妙妙屋

最新文章

  • Visual Stdio 2017显示UTF-8字符串(中文的情况下),字符串中的字符无效
  • WebStorm-2018.2.2配置
  • Sublime Text 3 配置
2020年1篇
2018年2篇
2017年71篇
2016年23篇
2015年35篇
2014年91篇
2013年32篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家五华区设计玻璃钢雕塑哪家好莆田园林玻璃钢雕塑公司滁州户外玻璃钢雕塑济南多彩玻璃钢雕塑供应商河北通道商场美陈生产企业郑州标识玻璃钢仿铜雕塑公司贵港玻璃钢雕塑作品云南肖像玻璃钢景观雕塑福建手糊法玻璃钢雕塑定制定西仿真人物玻璃钢雕塑商场美陈安装验收单模板丹阳玻璃钢雕塑厂家联系方式漯河大型不锈钢玻璃钢雕塑厂家台州特色玻璃钢雕塑宣城定制玻璃钢雕塑承德玻璃钢马雕塑厂家直供高架玻璃钢花盆订购惠州玻璃钢雕塑价格厂娄底玻璃钢雕塑制作铜仁玻璃钢雕塑制作厂家扬州百货商场美陈江西城市景观雕塑玻璃钢韶关玻璃钢景观人物雕塑东莞有哪些玻璃钢花盆制品厂花盆玻璃钢花盆玻璃钢雕塑功夫熊猫枣庄广场玻璃钢雕塑新疆乌鲁木齐玻璃钢雕塑黑河动物玻璃钢雕塑公司福建商业商场美陈生产香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化