qt5.9.0 msvc2015优雅的崩溃:dumpfile

交给客户的软件奔溃了怎么办?

我们不能再客户电脑上安装vs,也不想傻傻的用log来猜测出错的地方。

利用Dbghelp可以解决这一问题。

首先是vs生成release版本的时候需要同时生成pdb文件,这里以vs2015为例:

https://blog.csdn.net/yhc166188/article/details/80695317

基本设置流程如下:

1、项目->属性->C/C++->General->Debug Information Format->Program Database for Edit & Continue (/ZI)

2、项目->属性->C/C++->Optimization->Optimization->Disabled(/Od)

3、项目->属性->Linker->Debugging->Generate Debug Info->Yes(/DEBUG)

此时,再编译软件,就会同时生成.pdb文件。

扫描二维码关注公众号,回复: 1912633 查看本文章

回到项目中来,我们还需要添加一点代码,使得程序优雅的奔溃。

新建一个dumpfile.h文件,将以下代码拷贝进去

  1 #pragma once
  2 #include <windows.h>
  3 #include < Dbghelp.h>
  4 #include <iostream>  
  5 #include <vector>  
  6 #include <tchar.h>  
  7 using namespace std;
  8 
  9 
 10 #pragma comment(lib, "Dbghelp.lib")
 11 
 12 
 13 namespace NSDumpFile
 14 {
 15     void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)
 16     {
 17         // 创建Dump文件  
 18         //  
 19         HANDLE hDumpFile = CreateFile(lpstrDumpFilePathName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 20 
 21 
 22         // Dump信息  
 23         //  
 24         MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
 25         dumpInfo.ExceptionPointers = pException;
 26         dumpInfo.ThreadId = GetCurrentThreadId();
 27         dumpInfo.ClientPointers = TRUE;
 28 
 29 
 30         // 写入Dump文件内容  
 31         //  
 32         MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
 33 
 34 
 35         CloseHandle(hDumpFile);
 36     }
 37 
 38 
 39     LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
 40     {
 41         return NULL;
 42     }
 43 
 44 
 45     BOOL PreventSetUnhandledExceptionFilter()
 46     {
 47         HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
 48         if (hKernel32 == NULL)
 49             return FALSE;
 50 
 51 
 52         void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");
 53         if (pOrgEntry == NULL)
 54             return FALSE;
 55 
 56 
 57         unsigned char newJump[100];
 58         DWORD dwOrgEntryAddr = (DWORD)pOrgEntry;
 59         dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far
 60 
 61 
 62         void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
 63         DWORD dwNewEntryAddr = (DWORD)pNewFunc;
 64         DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;
 65 
 66 
 67         newJump[0] = 0xE9;  // JMP absolute
 68         memcpy(&newJump[1], &dwRelativeAddr, sizeof(pNewFunc));
 69         SIZE_T bytesWritten;
 70         BOOL bRet = WriteProcessMemory(GetCurrentProcess(), pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten);
 71         return bRet;
 72     }
 73 
 74     LONG WINAPI UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS *pException)
 75     {
 76         TCHAR szMbsFile[MAX_PATH] = { 0 };
 77         ::GetModuleFileName(NULL, szMbsFile, MAX_PATH);
 78         TCHAR* pFind = _tcsrchr(szMbsFile, '\\');
 79         if (pFind)
 80         {
 81             *(pFind + 1) = 0;
 82             _tcscat(szMbsFile, _T("CrashDumpFile.dmp"));
 83             CreateDumpFile(szMbsFile, pException);
 84         }
 85 
 86 
 87         // TODO: MiniDumpWriteDump
 88         FatalAppExit(-1, _T("Fatal Error"));
 89         return EXCEPTION_CONTINUE_SEARCH;
 90     }
 91 
 92 
 93     void RunCrashHandler()
 94     {
 95         SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);
 96         PreventSetUnhandledExceptionFilter();
 97     }
 98 };
 99 
100 
101 #define DeclareDumpFile() NSDumpFile::RunCrashHandler();

接着,在全局类(例如main文件,或者QMainWindow派生类)里面添加头文件dumpfile.h,然后在构造函数或者全局添加宏:

DeclareDumpFile()即可。
#include "StockTradeByTdxMulti.h"
#include <QtWidgets/QApplication>
#include <QFile>
#include "dumpfile.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    DeclareDumpFile()
    StockTradeByTdxMulti w;
    w.show();
    return a.exec();
}

如果exe出错了,就会生成CrashDumpFile.dmp文件,当然你也可以改成你希望的名字。

最后,你从客户那边拿到CrashDumpFile.dmp,放到上面说的.pdb文件所在文件夹。双击运行CrashDumpFile.dmp,vs就会运行起来。

点击画圈的部分就可以定位到代码出错的位置啦。

猜你喜欢

转载自www.cnblogs.com/rmdmn/p/9274060.html