Windows平台下Qt程序崩溃处理
写一个客户端软件难免会出现异常崩溃的情况,出现问题不可怕,可怕的是不知道问题出在哪里。
这篇博客主要介绍一种Windows平台下c++程序的异常崩溃处理方法,文章中是针对Qt程序。
参考了网络上一些文章,如有版权等问题还请见谅,请随时与我联系。
参考地址:
https://www.cnblogs.com/lcchuguo/p/5177715.html
https://blog.csdn.net/baidu_33570760/article/details/52221863
主要知识点
- SetUnhandledExceptionFilter
SetUnhandledExceptionFilter函数是Win32API的异常捕获函数,在程式异常结束前。会调用该函数注冊的回调函数,这样就能在进程终止前运行指定的代码,达到比如保存数据的功能。 - DbgHelp
微软提供了“DbgHelp”错误调试技术。调用相关功能就可以保存程式崩溃时的信息。
调用“DbgHelp”的MiniDumpWriteDump函数保存以“.dmp”为后缀的Dump文件。
主程序实现
1. 需要引用的头文件
#include <Windows.h>
#include <DbgHelp.h>
2. 需要添加的链接库
LIBS += -lDbgHelp
3. release下生成调试信息,在pro文件中添加
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO
4. 主要代码实现
#include <QApplication>
#include <Windows.h>
#include <string>
#include <DbgHelp.h>
#include <QDateTime>
#include <QMessageBox>
using namespace std;
#pragma comment(lib, "DbgHelp.Lib")
#ifdef Q_OS_WIN
#pragma execution_character_set("utf-8") //解决 VS编译器下中文乱码
#endif
LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException) {//程式异常捕获
//创建 Dump 文件
QString filename = QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss-zzz") + ".dmp";
HANDLE hDumpFile = CreateFile(filename.toStdWString().c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDumpFile != INVALID_HANDLE_VALUE) {
//Dump信息
MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
dumpInfo.ExceptionPointers = pException;
dumpInfo.ThreadId = GetCurrentThreadId();
dumpInfo.ClientPointers = TRUE;
//写入Dump文件内容
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
}
//这里弹出一个错误对话框并退出程序
EXCEPTION_RECORD* record = pException->ExceptionRecord;
QString errCode(QString::number(record->ExceptionCode, 16)), errAdr(QString::number((uint)record->ExceptionAddress, 16)), errMod;
QMessageBox::critical(NULL, "程式崩溃", "<FONT size=4><div><b>对于发生的错误,表示诚挚的歉意</b><br/></div>" +
QString("<div>错误代码:%1</div><div>错误地址:%2</div></FONT>").arg(errCode).arg(errAdr),
QMessageBox::Ok);
return EXCEPTION_EXECUTE_HANDLER;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);//注冊异常捕获函数
int *x = 0;
*x = 100;
return a.exec();
}
分析dmp文件
使用winDbg
安装winsdk可以选择安装winDbg,也可以单独安装,这个用的不多,不加叙述。
使用vs
使用vs打开dmp文件,选择【使用 仅限本机 进行调试】
vs写的项目还可以设置源代码和【设置符号路径】,我用Qt生成的dmp直接可以定位到源码。
问题点总结
1. Qt编码问题
编码问题最直接的就是会导致中文乱码以及QString和string的转换,Qt程序里解决编码问题我常用的有两种方法:
- 在代码文件中添加如下代码
#ifdef Q_OS_WIN #pragma execution_character_set("utf-8") //解决 VS编译器下中文乱码 #endif
- 直接在pro文件中添加如下代码
win32-msvc*: { QMAKE_CFLAGS *= /utf-8 QMAKE_CXXFLAGS *= /utf-8 }
2. 引用lib文件
引用lib文件可以在pro文件中添加,也可以在代码中添加
-
代码中:
#pragma comment(lib, "DbgHelp.Lib")
-
pro文件中
LIBS += -lDbgHelp
3. LPCWSTR类型错误
LPCWSTR是宽字节。
在vs中可以在【配置属性】-【常规】-【字符集】-【使用多字节字符集】设置。
Qt中只能是QString::toStdWString()
4. release模式下生成pdb文件
release下生成调试信息,在pro文件中添加
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO