Qt MSVC_64bit在Release模式下调试与WinDbg调试exe
本文介绍了在Qt Release模式下调试和崩溃分析的方法。首先在.pro文件中添加调试信息配置,生成带.pdb的Release版本,实现QtCreator调试功能。其次通过注册异常处理函数,使用MiniDumpWriteDump生成崩溃dump文件。最后详细说明使用WinDbg分析dump文件的具体步骤:设置符号表路径、加载dump文件后,通过!analyze-v和.excr命令定位崩溃位置。该
1、前言
在一次Qt编程时,使用到第三方库,但是第三方库是Release版本,所以Qt开发也需要是Release版本,但是无法直接Debug调试,需要进行设置,另外为了生成exe后,可以通过WinDbg排查程序崩溃问题,在此进行记录,方便自己后续查看。
项目为QtCreator,使用MSVC2017 64bit编译
2、Qt在Release模式下调试并生成.pdb文件
在项目的.pro文件中添加如下设置,并右键项目,按照顺序依次选择qmake、重新构建项目
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO


在生成项目后,exe目录中会同时生成.pdb文件

此时已经可以再QtCreator中在Release模式时正常Debug调试了

3、WinDbg调试Dump文件
3.1、将程序崩溃时的执行信息保存为dump文件
这部分网上文章较多,在windows系统下的主要思路是:
-
使用
SetUnhandledExceptionFilter注册程序的异常捕获回调函数; -
将捕获的异常通过
MiniDumpWriteDump函数保存。
注意:需要先在.pro文件里加入LIBS += -lDbgHelp
#pragma execution_character_set("utf-8")
#include "mainwindow.h"
#include <QApplication>
#include <QMessageBox>
#include <QDir>
#include <QDebug>
#include <QDateTime>
#include <QTextCodec>
#include <windows.h>
#include <DbgHelp.h>
// 保存程序异常崩溃的信息
LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException)
{
//初始化dump文件夹
QString logFilePath = QCoreApplication::applicationDirPath() + "/DumpCrashes/";
QDir dstDir(logFilePath);
if(!dstDir.exists())
{
if(!dstDir.mkpath(logFilePath))
{
qDebug()<<__FILE__<<__LINE__<<"创建DumpCrashes文件夹失败!";
}
}
//创建Dump文件
QString dumpFileName = logFilePath + QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss") + ".dmp";
HANDLE hDumpFile = CreateFile((LPCWSTR)(dumpFileName.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, (MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithProcessThreadData | MiniDumpWithUnloadedModules), &dumpInfo, NULL, NULL);
}
//这里弹出一个错误对话框并退出程序
EXCEPTION_RECORD* record = pException->ExceptionRecord;
QString errCode(QString::number(record->ExceptionCode,16));
QString errAddr(QString::number((uint)record->ExceptionAddress,16));
QMessageBox::critical(NULL,"错误",QString("程序异常崩溃捕获!\nerrCode:%1 \nerrAddr:%2").arg(errCode.toStdString().c_str()).arg(errAddr.toStdString().c_str()));
return EXCEPTION_EXECUTE_HANDLER;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//注冊异常捕获函数
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
MainWindow w;
w.show();
return a.exec();
}
此时,当出现运行崩溃时,将会弹出提示框,提示异常捕获,并在exe所在目录中出现“DumpCrashes”文件夹,在文件夹中存在以异常出现日期时间为文件名的.dmp后缀文件(此项目为了测试而设置了明显的崩溃问题)



3.2、使用 WinDbg 分析dump文件
- 打开WinDbg(x64)(windbg.exe);
- File —> Symbol File Path,设置.pdb文件所在的文件夹(注意是文件夹,而不是文件);
- File —> Source File Path,设置release版本的.exe执行文件所在的文件夹;
- File —> Open Crash Dump,打开crash.dmp文件。

出现Command窗口

3.3、在窗口中进行代码分析
点击或在下方输入栏输入!analvze -v并回车
!analvze -v

点击或在下方输入栏输入.excr 切换到发生异常的线程上下文中
.excr

将会打开源码中报错位置与代码

4、最后
以上方法为本人测试使用,如有问题,欢迎指正。
另外,参考了Qt程序Release版本记录崩溃信息,并定位问题代码以及Windows下Release版本Qt程序生成日志和dump文件(用于程序异常崩溃检测)两位大佬的文章,感谢大佬的分享。
更多推荐



所有评论(0)