Qt MSVC_64bit在Release模式下调试与WinDbg调试exe
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文件(用于程序异常崩溃检测)两位大佬的文章,感谢大佬的分享。