C++生成dump文件

C++代码中,使用DbgHelp模块的MINIDUMP编程生成

#include "DbgHelp.h"
typedef BOOL (WINAPI* MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
                                               CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
                                                CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
                                                CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);

long CSE_Exception::_DbgDumpError(struct _EXCEPTION_POINTERS *excpInfo, LPCTSTR szPrex )
{

     LONG retval = EXCEPTION_CONTINUE_SEARCH;

     HMODULE hDll = ::LoadLibrary(_T("DBGHELP.DLL"));
     LPCTSTR szResult = NULL;
     MINIDUMPWRITEDUMP pDump = NULL;

     if (hDll)
         pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll,"MiniDumpWriteDump");

     if (pDump)
     {
         TCHAR szDumpPath [_MAX_PATH] = {0};
         TCHAR szDumpFile [_MAX_PATH] = {0};
         GetModuleFileName(NULL, szDumpPath, _MAX_PATH);
         _tcsrchr(szDumpPath, _T(‘\\‘))[1] = 0;
         _tcscat(szDumpPath, _T("..\\logs\"));

         time_t timeCurrent = time(0);
         struct tm* tmc = localtime(&timeCurrent);
         if ( tmc )
              _stprintf(szDumpFile, _T("%s%d_%d_%d_%d_%d.dmp"), szPrex, tmc->tm_mon+1, tmc->tm_mday, tmc->tm_hour, tmc->tm_min, tmc->tm_sec);
         else
              _tcscpy(szDumpFile, _T("error.dmp"));
         _tcscat(szDumpPath, szDumpFile);

         // create the file
         HANDLE hFile = ::CreateFile( szDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
              FILE_ATTRIBUTE_NORMAL, NULL );

         if (hFile!=INVALID_HANDLE_VALUE)
         {
              if (excpInfo == NULL) //如果没有传入异常, 比如是在程序里面调用的, 生成一个异常
              {
                   // Generate exception to get proper context in dump

                   DWORD dwSize = 0;
                   char *sz = "_EXCEPTION_POINTERS is null";
                   ::WriteFile(hFile, sz, strlen(sz), &dwSize, NULL);
              }
              else
              {
                   MINIDUMP_EXCEPTION_INFORMATION eInfo;
                   eInfo.ThreadId = GetCurrentThreadId(); //把需要的信息添进去
                   eInfo.ExceptionPointers = excpInfo;
                   eInfo.ClientPointers = FALSE;

                   // Dump的类型是小型的, 节省空间. 可以参考MSDN生成更详细的Dump.
                   pDump(
                       GetCurrentProcess(),
                       GetCurrentProcessId(),
                       hFile,
                       MiniDumpNormal,
                       excpInfo ? &eInfo : NULL,
                       NULL,
                       NULL);
              }
              ::CloseHandle(hFile);

         }
     }
     if( hDll )
         ::FreeLibrary(hDll);

     return retval;
}

void CSE_Exception::InitSEException()
{
     _set_se_translator( CSE_Exception::trans_func );
}

void CSE_Exception::_DumpCallStack()
{
     __try
     {
         __try
         {
              RaiseException(1, 0, 0, NULL);
         }
         __finally
         {
         }
     }
     __except(_DbgDumpError(GetExceptionInformation(), _T("T")),
         EXCEPTION_CONTINUE_EXECUTION)
     {
     }
}

void CSE_Exception::trans_func( unsigned int uSENum, _EXCEPTION_POINTERS* pExp )
{
#define SE_BUF_SIZE         250
     TCHAR pszBuf[SE_BUF_SIZE+2];

     _DbgDumpError(pExp, _T("e"));
     switch(uSENum)
     {
     case EXCEPTION_ACCESS_VIOLATION:
         _sntprintf(pszBuf, SE_BUF_SIZE, _T("Access Violation: IP: 0xX %s Address: 0xX"),
              pExp->ExceptionRecord->ExceptionAddress, pExp->ExceptionRecord->ExceptionInformation[0]?_T("Write"):_T("Read"), pExp->ExceptionRecord->ExceptionInformation[1]);
         break;
     case EXCEPTION_INT_DIVIDE_BY_ZERO:
         _sntprintf(pszBuf, SE_BUF_SIZE, _T("INT_DIVIDE_BY_ZERO"));
         break;
     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
         _sntprintf(pszBuf, SE_BUF_SIZE, _T("FLT_DIVIDE_BY_ZERO"));
         break;
     case EXCEPTION_ILLEGAL_INSTRUCTION:
         _sntprintf(pszBuf, SE_BUF_SIZE, _T("ILLEGAL_INSTRUCTION"));
         break;
     case EXCEPTION_PRIV_INSTRUCTION:
         _sntprintf(pszBuf, SE_BUF_SIZE, _T("EXCEPTION_PRIV_INSTRUCTION"));
         break;
     case EXCEPTION_STACK_OVERFLOW:
         _sntprintf(pszBuf, SE_BUF_SIZE, _T("EXCEPTION_STACK_OVERFLOW"));
         break;
     default:
         _sntprintf(pszBuf, SE_BUF_SIZE, _T("Unknown SE_exception: X"), uSENum);
         break;
     }

     CSE_Exception e(pszBuf);
     e.m_nSENumber = uSENum;
     e.m_SERecord  = *(pExp->ExceptionRecord);
     e.m_SEContext  = *(pExp->ContextRecord);

     throw e;
}

  然后在程序的InitInstance中加入代码如下:

LONG WINAPI DbgUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
{
     CSE_Exception::_DbgDumpError(pExceptionInfo, _T("E"));
     return EXCEPTION_CONTINUE_SEARCH;    // 程序停止运行
}
BOOL CDCPWorkerApp::InitInstance()
{
     //EHA
     CSE_Exception::InitSEException();
     //捕获未处理的异常
     SetUnhandledExceptionFilter(DbgUnhandledExceptionFilter);
}

  

时间: 2024-11-11 14:02:45

C++生成dump文件的相关文章

WinDBG 技巧:如何生成Dump 文件(.dump 命令)

程序崩溃(crash)的时候, 为了以后能够调试分析问题, 可以使用WinDBG要把当时程序内存空间数据都保存下来,生成的文件称为dump 文件. 步骤: 1) 打开WinDBG并将之Attach 到crash的程序进程 2) 输入产生dump 文件的命令 WinDBG产生dump 文件的命令是 .dump ,可以选择不同的参数来生成不同类型的dump文件. 选项(1): /m 命令行示例:.dump /m C:\dumps\myapp.dmp 注解: 缺省选项,生成标准的minidump, 转

使用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(

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

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

如何设置C++崩溃时生成Dump文件

Dump 文件是进程的内存镜像 , 可以把程序的执行状态通过调试器保存到dump文件中 ; Dump 文件是用来给驱动程序编写人员调试驱动程序用的 , 这种文件必须用专用工具软件打开 , 比如使用 WinDbg , VisualStudio 打开 ; 当我们的程序发布出去之后 , 在客户机上是无法跟踪自己代码的 BUG 的 , 所以 Dump 文件对于我们来说特别有用 ; 我们可以通过 .dmp 文件把出现 BUG 的情况再现 , 然后再现客户环境 (包括堆栈调用等情况) , 设置源码调试路径

JVM 在遇到OOM(OutOfMemoryError)时生成Dump文件的三种方式

JVM 在遇到OOM(OutOfMemoryError)时生成Dump文件的三种方式,以及如何使用Eclips Memory Analyzer(MAT)插件进行堆内存分析. 方法一: jmap -dump:format=b,file=文件名 [pid] 例如: jmap -dump:format=b,file=/usr/local/base/02.hprof 12942 方法二: 让JVM在遇到OOM(OutOfMemoryError)时生成Dump文件,需要配置一些信息 -XX:+HeapDu

JVM生成dump文件方式

JVM生成dump文件一般有两种方式 一. 出现OOM时自动生成堆dumpJVM启动命令增加两个参数:-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/home/app/dumps/ 二.人工通过执行指令,直接生成当前JVM的dump文件例如:jmap -dump:format=b,file=/home/app/testdump.hprof 6218其中6218是JVM的当前进程号 原文地址:https://www.cnblogs.com/xing

Windows下生成dump文件方法

[转载请注明出处]:http://blog.csdn.net/longlong530 一. 背景 没人能保证自己的软件在各种未知环境运行下,会木有任何问题.那么如果程序崩溃了怎么办?看日志?日志不全又怎么办?日志能帮你定位的多细致呢?如果能有种方法记录程序最后工作的状态,比如堆栈调用情况等,那么我们就可以获悉"它是如何挂掉的~" 二. 调研 我们对程序bug引起的程序崩溃的五种定位方法进行了调研,并最终选择方案5为我所在项目使用的程序崩溃定位方案. 方案1: 崩溃地址 + MAP文件

windows生成dump文件

windows下程序有时突然崩溃了,偶发性的崩溃很难找.于是就需要保存崩溃时的dump信息了. 下面是关于如何生成dmp文件的代码. 头文件 #pragma once #include <windows.h> #include <DbgHelp.h> #include <stdlib.h> #include <string> #pragma comment(lib, "dbghelp.lib") namespace FrameworkMi