1. 程式人生 > >dump生成與分析

dump生成與分析

來源:

軟體發生異常,沒有除錯環境,怎麼快速定位問題?遇到這類問題,最有的資訊就是生成dump檔案,然後通過dump檔案檢視callstack等資訊定位。

 

Dump檔案生成原理:

dbghelp使用SetUnhandledExceptionFilter設定回撥函式生成dump檔案,後分析異常地方。

本文實現方式:分裝類在MFC程式中呼叫並分析

1、類的實現

//CreateDump.h
#pragma once
#include <string>
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    strDumpFile; 
    static CCreateDump*    __instance;
};

//CreateDump.cpp
#include "stdafx.h"
#include "CreateDump.h"
#include <DbgHelp.h>
#pragma comment(lib,  "dbghelp.lib")

CCreateDump* CCreateDump::__instance = NULL;
std::string CCreateDump::strDumpFile = "";

CCreateDump::CCreateDump()
{
}

CCreateDump::~CCreateDump(void)
{
    
}

long  CCreateDump::UnhandleExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo)
{

    HANDLE hFile   =   CreateFileA(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   dump
        BOOL   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 c[MAX_PATH];
    sprintf_s(c,MAX_PATH,"[%04d-%02d-%02d %02d:%02d:%02d]",syt.wYear,syt.wMonth,syt.wDay,syt.wHour,syt.wMinute,syt.wSecond);
    strDumpFile = std::string(c);
    if (!dmpFileName.empty())
    {
        strDumpFile += dmpFileName;
    }
    strDumpFile += std::string(".dmp");
    SetUnhandledExceptionFilter(UnhandleExceptionFilter);
}

CCreateDump* CCreateDump::Instance()
{
    if (__instance == NULL)
    {
        __instance = new CCreateDump;
    }
    return __instance;
}


2、呼叫和產生方式

在程式初始化時候呼叫:

CCreateDump::Instance()->DeclarDumpFile("dumpfile");

3寫出異常程式碼

int a = 9;

int b = 0;

int c = 0;

c = a / b;

執行程式,並執行此處程式碼(執行目錄下生成dump檔案)

4、把dmp檔案和exe, pdb檔案放在同一目錄下,然後用編譯器(vc)開啟dmp檔案,然後開始除錯就會中斷到剛才異常的地方。