Windows平台下Qt程序崩溃处理

写一个客户端软件难免会出现异常崩溃的情况,出现问题不可怕,可怕的是不知道问题出在哪里。
这篇博客主要介绍一种Windows平台下c++程序的异常崩溃处理方法,文章中是针对Qt程序。
参考了网络上一些文章,如有版权等问题还请见谅,请随时与我联系。
参考地址:
https://www.cnblogs.com/lcchuguo/p/5177715.html
https://blog.csdn.net/baidu_33570760/article/details/52221863

主要知识点

  1. SetUnhandledExceptionFilter
    SetUnhandledExceptionFilter函数是Win32API的异常捕获函数,在程式异常结束前。会调用该函数注冊的回调函数,这样就能在进程终止前运行指定的代码,达到比如保存数据的功能。
  2. 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
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是Qt程序崩溃异常捕获的方法: 1.使用qInstallMessageHandler()函数来自定义消息处理程序,以便在程序崩溃时获取相关信息。以下是一个示例代码: ```cpp void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QByteArray localMsg = msg.toLocal8Bit(); switch (type) { case QtDebugMsg: fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtInfoMsg: fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtWarningMsg: fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtCriticalMsg: fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtFatalMsg: fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); abort(); } } int main(int argc, char *argv[]) { qInstallMessageHandler(myMessageOutput); QApplication a(argc, argv); // ... return a.exec(); } ``` 2.使用Qt的调试器来捕获异常。在Qt Creator中,可以通过以下步骤来使用调试器: - 在Qt Creator中打开项目并设置断点。 - 单击“调试”按钮以启动调试器。 - 在调试器中运行程序并观察变量和堆栈。 - 如果程序崩溃,调试器将停止并显示崩溃信息。 3.使用第三方库来捕获异常,例如Google Breakpad。Google Breakpad是一个开源库,可用于在Windows、Linux和Mac OS X上捕获程序崩溃信息。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值