[Windows]_[初级]_[Release程序的崩溃报告minidump解决方案]

来源:互联网 发布:肩膀疼 知乎 编辑:程序博客网 时间:2024/06/15 04:33


场景:

1. Release的程序崩溃时,崩溃报告可以让开发人员查明代码哪里出了问题,用处大大的。

2. 只有用VS的编译器才支持,所以MinGW就无缘了。

3. 使用了未处理异常过滤处理函数.

4. 生成的.dmp文件用zlib库压缩, 用到以下的ZipHelper类,编译时还是需要zlib库和dbghelp.lib

http://blog.csdn.net/infoworld/article/details/41290969


5. 使用方式就是把DbgReport作为app类的成员变量,或者文件范围的全局变量初始化后,在程序运行开始前调用

RegisterCrashFilter

6. 更新: 增加VC CRT异常捕抓. 2015-09-25

参考:

http://blog.csdn.net/limiteee/article/details/8472179



bas_dbg_report.h

#ifndef __BAS_DBG_REPORT#define __BAS_DBG_REPORT#include "bas_exp.h"//1.可以自己修改参数,添加额外信息.typedef void (*BASReportCallbackFunc)(const wchar_t* dump_zip_path);class LIB_BASIC BASDbgReport{public:void RegisterCrashFilter(const wchar_t* dump_path,BASReportCallbackFunc func);};#endif


bas_dbg_report.cpp

#include "basic/bas_dbg_report.h"#include <Windows.h>#include <DbgHelp.h>#include "basic/bas_utility_string.h"#include "basic/bas_wrap_object.h"#include "basic/bas_utility_zip.h"static std::wstring gDumpPath;static std::wstring gDumpZipPath;static BASReportCallbackFunc gReportCallbackFunc = NULL;static BOOL IsDataSectionNeeded(const WCHAR* pModuleName)  {      if(pModuleName == NULL)      {          return FALSE;      }        WCHAR szFileName[_MAX_FNAME] = L"";      _wsplitpath(pModuleName, NULL, NULL, szFileName, NULL);        if(wcsicmp(szFileName, L"ntdll") == 0)          return TRUE;        return FALSE;  } static 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;  } static LONG WINAPI TopLevelUnhandledExceptionFilter(PEXCEPTION_POINTERS pExInfo){HANDLE hFile = ::CreateFile( gDumpPath.c_str(), GENERIC_WRITE, 0, NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);if( hFile != INVALID_HANDLE_VALUE){MINIDUMP_EXCEPTION_INFORMATION einfo;einfo.ThreadId = ::GetCurrentThreadId();einfo.ExceptionPointers = pExInfo;einfo.ClientPointers = FALSE;MINIDUMP_CALLBACK_INFORMATION mci;  mci.CallbackRoutine     = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;  mci.CallbackParam       = NULL;  ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), hFile,MiniDumpNormal,&einfo, NULL, &mci);::CloseHandle(hFile);}//1.压缩dmp文件和其他char* utf8 = BASUtilityString::ConvertUnicodeToUtf8(gDumpPath.c_str());BASWrapMalloc wm1(utf8);BASUtilityZip z;z.AddFile(utf8);std::string output(utf8);output.append(".zip");wchar_t* unicode = BASUtilityString::ConvertUtf8ToUnicode(output.c_str());BASWrapMalloc wm2(unicode);gDumpZipPath.append(unicode);z.ToZip(output.c_str());if(gReportCallbackFunc){gReportCallbackFunc(gDumpZipPath.c_str());}return EXCEPTION_EXECUTE_HANDLER;}static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(    LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter){return NULL;}static BOOL PreventSetUnhandledExceptionFilter(){    HMODULE hKernel32 = LoadLibrary(L"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;  }void BASDbgReport::RegisterCrashFilter(const wchar_t* dump_path,BASReportCallbackFunc func){#ifndef _DEBUGgDumpPath.append(dump_path);gReportCallbackFunc = func;SetUnhandledExceptionFilter(TopLevelUnhandledExceptionFilter);//BOOL bRet = PreventSetUnhandledExceptionFilter(); //这个部分系统会崩溃,暂时不使用.#endif}



0 0
原创粉丝点击