代码部分
依赖库 DbgHelp
win下直接链接引入即可: target_link_libraries(${PROJECT_NAME} DbgHelp)
头文件引入
#include <DbgHelp.h>
win异常处理函数注册
#ifdef WIN32
// 注册异常处理函数
LPTOP_LEVEL_EXCEPTION_FILTER Top = SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
// 此函数与搜狗输入法冲突,会导致编译不过或程序运行崩溃
// DisableSetUnhandledExceptionFilter();
#endif
异常处理执行函数代码如下
#ifdef WIN32
// 崩溃相关处理函数
LONG WINAPI ApplicationCrashHandler(EXCEPTION_POINTERS *pException){
//这里弹出一个错误对话框并退出程序
EXCEPTION_RECORD* record = pException->ExceptionRecord;
QString errCode(QString::number((uint)record->ExceptionCode,16)),
errAdr(QString::number(PtrToInt(record->ExceptionAddress),16)),
errMod;
// 崩溃日志写入
LOG_ERROR(QString::fromLocal8Bit("错误代码:%1 错误地址:%2").arg(errCode).arg(errAdr).toStdString().c_str());
// 创建错误文件
HANDLE dumpFile = CreateFile((LPCWSTR)QString("./error.dmp").utf16(),GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(dumpFile != INVALID_HANDLE_VALUE)
{
MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
dumpInfo.ExceptionPointers = pException;
dumpInfo.ThreadId = GetCurrentThreadId();
dumpInfo.ClientPointers = TRUE;
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
CloseHandle(dumpFile);
LOG_INFO(QString::fromLocal8Bit("调试信息生成成功。").toStdString().c_str());
}else{
LOG_ERROR(QString::fromLocal8Bit("调试信息文件生成失败。").toStdString().c_str());
}
QMessageBox::critical(NULL,
QString::fromLocal8Bit("程式崩溃"),
QString::fromLocal8Bit("<FONT size=4><div><b>对于发生的错误,表示诚挚的歉意</b><br/></div>")+
QString::fromLocal8Bit("<div>错误代码:%1</div><div>错误地址:%2</div></FONT>").arg(errCode).arg(errAdr),
QMessageBox::Ok);
//EXCEPTION_EXECUTE_HANDLER
return EXCEPTION_EXECUTE_HANDLER;
// return EXCEPTION_CONTINUE_EXECUTION;
}
//防止CRT(C runtime)函数报错可能捕捉不到,这里与搜狗输入法存在bug,回到这程序起不来(暂时不执行此函数)
void DisableSetUnhandledExceptionFilter()
{
void* addr = (void*)GetProcAddress(LoadLibrary(L"kernel32.dll"), "SetUnhandledExceptionFilter");
if(addr)
{
unsigned char code[16];
int size = 0;
code[size++] = 0x33;
code[size++] = 0xC0;
code[size++] = 0xC2;
code[size++] = 0x04;
code[size++] = 0x00;
DWORD dwOldFlag, dwTempFlag;
VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);
VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);
}
}
#endif
文件处理过程
在程序崩溃后会在指定目录下生成dmp文件(代码内指定了./error.dmp),正常在根目录找到error.dmp文件拖拽到visual studio中,右侧红框内可选择对应pdb进行调试。