qt5.9.0 msvc2015优雅的崩溃:dumpfile
阅读原文时间:2023年07月11日阅读:2

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

我们不能再客户电脑上安装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文件,将以下代码拷贝进去

#pragma once
#include
#include < Dbghelp.h>
#include
#include
#include
using namespace std;

#pragma comment(lib, "Dbghelp.lib")

namespace NSDumpFile
{
void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)
{
// 创建Dump文件
//
HANDLE hDumpFile = CreateFile(lpstrDumpFilePathName, GENERIC_WRITE, , NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

     // Dump信息  
     //  
     MINIDUMP\_EXCEPTION\_INFORMATION dumpInfo;  
     dumpInfo.ExceptionPointers = pException;  
     dumpInfo.ThreadId = GetCurrentThreadId();  
     dumpInfo.ClientPointers = TRUE;

     // 写入Dump文件内容  
     //  
     MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

     CloseHandle(hDumpFile);  
 }

 LPTOP\_LEVEL\_EXCEPTION\_FILTER WINAPI MyDummySetUnhandledExceptionFilter(LPTOP\_LEVEL\_EXCEPTION\_FILTER lpTopLevelExceptionFilter)  
 {  
     return NULL;  
 }

 BOOL PreventSetUnhandledExceptionFilter()  
 {  
     HMODULE hKernel32 = LoadLibrary(\_T("kernel32.dll"));  
     if (hKernel32 == NULL)  
         return FALSE;

     void \*pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");  
     if (pOrgEntry == NULL)  
         return FALSE;

     unsigned char newJump\[\];  
     DWORD dwOrgEntryAddr = (DWORD)pOrgEntry;  
     dwOrgEntryAddr += ; // add 5 for 5 op-codes for jmp far

     void \*pNewFunc = &MyDummySetUnhandledExceptionFilter;  
     DWORD dwNewEntryAddr = (DWORD)pNewFunc;  
     DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;

     newJump\[\] = 0xE9;  // JMP absolute  
     memcpy(&newJump\[\], &dwRelativeAddr, sizeof(pNewFunc));  
     SIZE\_T bytesWritten;  
     BOOL bRet = WriteProcessMemory(GetCurrentProcess(), pOrgEntry, newJump, sizeof(pNewFunc) + , &bytesWritten);  
     return bRet;  
 }

 LONG WINAPI UnhandledExceptionFilterEx(struct \_EXCEPTION\_POINTERS \*pException)  
 {  
     TCHAR szMbsFile\[MAX\_PATH\] = {  };  
     ::GetModuleFileName(NULL, szMbsFile, MAX\_PATH);  
     TCHAR\* pFind = \_tcsrchr(szMbsFile, '\\\\');  
     if (pFind)  
     {  
         \*(pFind + ) = ;  
         \_tcscat(szMbsFile, \_T("CrashDumpFile.dmp"));  
         CreateDumpFile(szMbsFile, pException);  
     }

     // TODO: MiniDumpWriteDump  
     FatalAppExit(-, \_T("Fatal Error"));  
     return EXCEPTION\_CONTINUE\_SEARCH;  
 }

 void RunCrashHandler()  
 {  
     SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);  
     PreventSetUnhandledExceptionFilter();  
 }  

};

#define DeclareDumpFile() NSDumpFile::RunCrashHandler();

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

DeclareDumpFile()即可。

#include "StockTradeByTdxMulti.h"
#include
#include
#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就会运行起来。

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

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章