交给客户的软件奔溃了怎么办?
我们不能再客户电脑上安装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就会运行起来。
点击画圈的部分就可以定位到代码出错的位置啦。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章