Windows下生成dump文件方法

【转载请注明出处】:http://blog.csdn.net/longlong530

一. 背景

没人能保证自己的软件在各种未知环境运行下,会木有任何问题。那么如果程序崩溃了怎么办?看日志?日志不全又怎么办?日志能帮你定位的多细致呢?如果能有种方法记录程序最后工作的状态,比如堆栈调用情况等,那么我们就可以获悉“它是如何挂掉的~”

二. 调研

我们对程序bug引起的程序崩溃的五种定位方法进行了调研,并最终选择方案5为我所在项目使用的程序崩溃定位方案。

方案1: 崩溃地址 + MAP文件

利用程序崩溃时产生的map文件来定位。这种方案只能对VC7以前的版本开发的程序使用

方案2: 崩溃地址 + MAP文件 + COD文件

这个方案主要是为了解决方案1的缺陷。由于VC8以后的版本都不再支持MAP文件中产生代码行信息,所以增加了COD文件的方法来定位问题。

方案3: 崩溃地址 + PDB文件 + CrashFinder

说明:前三种方案,其实只需要用户告知崩溃地址,然后在本地查找crash地址就可以了,但是定位crash的过程非常不方便,如果crash的情况比

较多,前三种方案都不合适。而且,前三种方案均不能生成堆栈调用信息,对于debug的作用有限。

方案4:SetUnhandledExceptionFilter + StackWalker

此方法需要pdb文件才能够正确生成堆栈调用的函数行号及代码行号,因此只适合本地release版的调试。

方案5:SetUnhandledExceptionFilter + Minidump

该方法是我们使用的捕获dump文件的工具,所以这里对其重点介绍一下。

三. 代码共享

核心代码如下:

#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <DbgHelp.h>

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

LONG WINAPI TopLevelFilter( struct _EXCEPTION_POINTERS *pExceptionInfo )
{
	// 返回EXCEPTION_CONTINUE_SEARCH,让程序停止运行
	LONG ret = EXCEPTION_CONTINUE_SEARCH;

	time_t  nowtime;
	time(&nowtime);
	struct tm *pTime = localtime(&nowtime);
	char szFile[128] = {0};

	// 设置core文件生成目录和文件名
	sprintf(szFile, "c:\\%4d.%02d.%02d_%02d.%02d.%02d.dmp", pTime->tm_year+1900, pTime->tm_mon+1, pTime->tm_mday, pTime->tm_hour, pTime->tm_min, pTime->tm_sec);

	HANDLE hFile = ::CreateFile(szFile, 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 = pExceptionInfo;
		ExInfo.ClientPointers = NULL;

		// write the dump
		BOOL bOK = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL );
		ret = EXCEPTION_EXECUTE_HANDLER;
		::CloseHandle(hFile);
	}

	return ret;
}

代码移植方法:

1  将下面的头文件拷贝到你的代码里

#include <time.h>

#include <windows.h>

#include <DbgHelp.h>

2  引入gdbhelp的静态库

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

3  将TopLevelFilter函数拷贝到你的代码里

4  在mian函数里,加入下面的代码

::SetUnhandledExceptionFilter(TopLevelFilter);

5  修改工程属性->配置属性->常规->项目默认值, 将字符集配置修改为使用多字节字符集

6  编译运行即可。

四. 代码解释

a)SetUnhandledExceptionFilter

SetUnhandledExceptionFilter 函数声明如下:

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(
      __in          LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
    );

SetUnhandleExceptionFilter允许我们设置一个自己的函数作为全局SEH过滤函数,当程序crash前会调用我们的函数进行处理。我们可以利用的

是 _EXCEPTION_POINTERS 结构类型的变量ExceptionInfo,它包含了对异常的描述以及发生异常的线程状态,过滤函数可以通过返回不同的值来

让系统继续运行或退出应用程序。

b) Minidump

Minidump:minidump(小存储器转储)可以理解为一个dump文件,里面记录了能够帮助调试crash的最小有用信息。实际上,如果你在 系统属性 ->

高级 -> 启动和故障恢复 -> 设置 -> 写入调试信息 中选择“小内存转储(64 KB)”的话,当系统意外停止时都会在C:\Windows\Minidump\路

径下生成一个.dmp后缀的文件,这个文件就是minidump文件,只不过这个是内核态的minidump。生成minidump文件的API函数:MiniDumpWriteDump,该函数需要dbghelp.lib支持。

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

调试dump文件首先需要pdb文件,因此我们build程序时需要设置 Debug Infomation Format 为 “Program Database(/Zi)”。其次,我们

还要确保所用的dump文件与源代码、exe、pdb文件版本是一致的,这要求我们必须维护好程序版本信息。调试minidump最方便的环境就是VS,

我们只要将.dmp、.exe、.pdb文件放在一个路径下,保证源代码文件的路径与编译时的路径一致就可以了,剩下的就是VS帮我们完成。双击.dmp

文件或者在文件打开工程中选择“dump files”,加载dump文件,然后按F5运行就能直接恢复crash时的现场了,你可以定位crash的代码,可以

查看调用堆栈,可以查看线程和模块信息.

五. 注意事项

对于release版的程序来说,很多代码是经过编译器优化过的,因此定位的时候可能会有所偏差,大家可以考虑设置选项去掉代码

优化。使用Minidump的详细方法可参见:http://vicchina.51.net/research/other/seh/minidumps/intro.htm

【转载请注明出处】:http://blog.csdn.net/longlong530

时间: 2024-11-10 00:49:15

Windows下生成dump文件方法的相关文章

Windows下获取Dump文件以及进程下各线程调用栈的方法总结(转)

1. Dump文件的用途 Dump文件, 主要用于诊断一个进程的运行状态,尤其是碰到崩溃(Crash)或者挂起(hang)不响应时,需要分析它的工作状态.  除了平时常见的attach到这个进程, 分析Dump文件就成了一个重要的手段了. 相信一些做软件维护和支持的工程师在这方面深有体会, 比如某天某时,客户说, 呀, 糟糕, 服务器进程挂掉了, 怎么回事? 然后,看看了日志文件,也没有什么可用的信息.  技术支持告诉他, 按某步骤生成一个dump文件来看看...... 2. 如何生成Dump文

调试SQLSERVER (一)生成dump文件的方法

调试SQLSERVER (一)生成dump文件的方法 调试SQLSERVER (二)使用Windbg调试SQLSERVER的环境设置调试SQLSERVER (三)使用Windbg调试SQLSERVER的一些命令 我们知道调试程序主要有两种方法 一种是:live debugging (附加进程 使进程hang住) 生产环境最好不要live debugging 一种是:post-mortem debugging or reading dump files (生成dump文件然后进行分析) 现在介绍一

windows下捕获dump之守护进程

一两个月前为产品写了一个独立的exe,由于产品使用的捕获dump是一个现成的进程外exe,如果以资源的方式集成它容易出现安全警告,由于时间关系没有寻求新的解决方法,还是遵循旧方案,不捕获dump. 最近业余看了会儿breakpad client,想到一个解决方案——其实也蛮简单的,最后exe大概会增加200多KB.下边从头分析. 有这样一种需求,希望一个进程启动之后,有另一个进程来“守护”它,当它发生crash时,能生成dump,然后把它重启:还有一个要求,“守护”进程跟工作进程必须是在同一个物

使用dbghelp生成dump文件以及事后调试分析

前言 在产品的实际应用环境中,如果我们的程序在客户那里出现了问题,例如程序异常了,而这个时候的现象又不能还原或者很难还原重现,那么只有使用dump文件来保存程序的当前运行信息,例如调用堆栈等,同时使用符号文件来定位问题了;这里主要讲解使用dbghelp库来生成输出dump文件,同时使用符号文件和windbg来分析问题.样例代码 1 #include "stdafx.h" 2 #include <Windows.h> 3 #include <iostream> 4

程序自动生成dump文件

作用 可以再程序崩溃后保留崩溃现场,方便事后查找程序的崩溃原因. 前提是奔溃程序所对应的代码和PDB文件都是匹配的(发布程序的时候,保留源代码和PDB文件). 代码示例 原理是使用DbgHelp的自定义未处理异常来保留崩溃现场到文件的,使用直接包含该头文件,然后再main函数的开始就调用EnableAutoDump函数. // pro_dump.h // 包含本文件是用来处理程序崩溃时自动生成dump文件的 // 生成的dump文件在程序的工作目录下 // 文件名格式是:年月日_时分秒.dmp

程序自动生成Dump文件()

前言:通过drwtsn32.NTSD.CDB等调试工具生成Dump文件, drwtsn32存在的缺点虽然NTSD.CDB可以完全解决,但并不是所有的操作系统中都安装了NTSD.CDB等调试工具.了解了mini dump文件格式后,完全可以程序自动生成Dump文件. 本文主要讨论以下内容: 1.  运行原理 2.  程序修改 3.  注意事项 一.   运行原理 当程序遇到未处理异常(主要指非指针造成)导致程序崩溃死,如果在异常发生之前调用了SetUnhandledExceptionFilter(

Windows下如何将一个文件夹通过Git上传到GitHub上(转)

在通过windows系统的电脑上写代码,需要将项目上传到GitHub上去.比如在Pycharm上写Django后端,整个项目是一个文件夹的形式,那么怎么才能这个文件夹通过Git命令上传到GitHub上呢? 以下给出详细步骤: 1.首先得安装git客户端 安装方法很简单,跟安装QQ之类的一样,进入官网:https://git-scm.com/ ,点击右侧下载windows版本的软件包,然后双击安装,一步一步下一步就可以了. 安装完成之后,在开始菜单可以看到如下就算是成功了: 此时,在任一文件夹上右

python在windows下UnicodeDecodeError的解决方法

之前在windows下使用python调用某些模块时都会报错,像这样: C:\Documents and Settings\Administrator>python -m CGIHTTPServer Traceback (most recent call last): File "C:\Python27\lib\runpy.py", line 162, in _run_module_as_main "__main__", fname, loader, pkg_

Windows下创建.gitgnore文件

相信使用过git的朋友可能遇到过,直接在windows下创建.gitgnore文件失败.类似截图那样 上网查了一下,有两种方法. 方法1: 此方法较为简单,前提是安装了git bash. 用git bash:cd 到 相应目录:然后输入命令touch .gitignore创建 方法2: 步骤1:在E:\Project\git_basic_homework创建一个1.txt文件 步骤2:按键盘Shift+键盘Ctrl+鼠标右击,选择'在此处打开命令窗口',弹出cmd命令框 步骤3:在cmd命令窗口