• 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文件。

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

    新建一个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就会运行起来。

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

  • 相关阅读:
    session监听
    Ubuntu上安装MongoDB(转)
    JAVA中的集合(转)
    Iterator的用法(转)
    PHPExcel常用方法汇总(转)
    MongoDB的安装及在PHP中的配置Windows版
    [转载]使用FastReport 3.0及以上版本创建动态报表的几个技巧
    FastReport
    ZeosLib
    [转载]FastReport问题整理
  • 原文地址:https://www.cnblogs.com/rmdmn/p/9274060.html
Copyright © 2020-2023  润新知