MFC程序RELEASE版本输出DUMP定位在代码行

有时给客户使用Release版本时,会偶尔出现崩溃的问题,这样很不好定位。但通过程序输出的dump文件可以定位到代码。

客户那边出现崩溃时,只需要把.dmp文件拷贝过来,然后放在工程.map和.pdb同级目录,然后用VS打开即可。具体过程如下:

1.在工程属性的release中设置如下,目的是产生DEBUG信息需要的.map和.pdb文件

2.在工程中添加dump.h头文件,

#pragma once  
#include <windows.h>  
#include <DbgHelp.h>  
#include <stdlib.h>  
#pragma comment(lib, "dbghelp.lib")  
  
#ifndef _M_IX86  
#error "The following code only works for x86!"  
#endif  
  
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;  
} 

inline void CreateMiniDump(PEXCEPTION_POINTERS pep, LPCTSTR strFileName)  
{  
    HANDLE hFile = CreateFile(strFileName, GENERIC_READ | GENERIC_WRITE,  
        FILE_SHARE_WRITE, 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     = NULL;  
  
        MINIDUMP_CALLBACK_INFORMATION mci;  
        mci.CallbackRoutine     = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;  
        mci.CallbackParam       = 0;  
  
        ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), hFile, MiniDumpNormal, (pep != 0) ? &mdei : 0, NULL, &mci);  
  
        CloseHandle(hFile);  
    }  
}  
  
LONG __stdcall MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)  
{  
    CreateMiniDump(pExceptionInfo, "dtcd8100Test.dmp");  
  
    return EXCEPTION_EXECUTE_HANDLER;  
}  
  
// 此函数一旦成功调用,之后对 SetUnhandledExceptionFilter 的调用将无效  
void DisableSetUnhandledExceptionFilter()  
{  
    void* addr = (void*)GetProcAddress(LoadLibrary("kernel32.dll"),  
        "SetUnhandledExceptionFilter");  
  
    if (addr)  
    {  
        unsigned char code[16];  
        int size = 0;  
  
        code[size++] = 0x33;  
        code[size++] = 0xC0;  
        code[size++] = 0xC2;  
        code[size++] = 0x04;  
        code[size++] = 0x00;  
  
        DWORD dwOldFlag, dwTempFlag;  
        VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);  
        WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);  
        VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);  
    }  
}  
  
void InitMinDump()  
{  
    //注册异常处理函数  
    SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);  
  
    //使SetUnhandledExceptionFilter  
    DisableSetUnhandledExceptionFilter();  
}  

3.在MFC工程的入口InitInstance中调用InitMinDump()即可。

4.程序崩溃后会在EXE同级目录下生成一个.dmp的文件,将它放在.pdb,.map同目录下。然后将.dmp文件拖动到VS中即可

5.然后点击红框即可跳转到代码行。(注意产生的dmp文件时代码要和分析时的一致)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值