文章目录
- 一、Pdb生成及Dump文件使用示例图
- 1.Pdb文件生成
- 2.Dump文件调试
- 3.参数不全Pdb生成的Dump文件调试
- 二、个人理解
- 1.生成Pdb文件的方式
- 2.Dump文件不生产的情况
- 三、源码
- Pro文件
- mian.cpp
- MainWindow
- Ui文件
- 总结
一、Pdb生成及Dump文件使用示例图
1.Pdb文件生成
下图先通过构建生成Pdb文件,然后运行程序,通过提前准备的崩溃按钮使得程序崩溃,生成“dump文件”的演示。
2.Dump文件调试
下图是先将之前生成的Pdb文件移动至dump文件同级目录,然后使用Visual Studio打开dump文件,在界面中点击使用’仅限本机’进行调试调试程序。
3.参数不全Pdb生成的Dump文件调试
下图使用的Pdb文件为是在缺少相关参数的状态下生成的(只有生成Pdb文件的命令符),可以看到打开后点击使用’仅限本机’进行调试调试程序显示的崩溃位置是异常的。
二、个人理解
1.生成Pdb文件的方式
我整合的的生成Pdb方式有多种,如下:
- 在Qt项目内容中配置添加"CONFIG += force_debug_info"(如下图),参考Qt-生成dump文件,该链接中还额外添加了"CONFIG+=separate_debug_info"的内容,但是我个人测试只添加"CONFIG += force_debug_info"也可以调试测试(测试范围不全面,欢迎指正)。(注:配置内容仅支持当前位置的项目,更换项目或者更换位置,都需要重新添加。)
- 在pro文件添加CONFIG += force_debug_info也可生成Pdb文件用于调试。(注:在Pro文件添加后,该项目任意位置可生成Pdb文件。)
- 在pro文件添加QMAKE_CXXFLAGS_RELEASE +=Q M A K E C F L A G S R E L E A S E W I T H D E B U G I N F O 和 Q M A K E L F L A G S R E L E A S E + = QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO和QMAKE_LFLAGS_RELEASE +=QMAKECFLAGSRELEASEWITHDEBUGINFO和QMAKELFLAGSRELEASE+=QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO可生成Pdb文件用于调试。**(注:在Pro文件添加后,该项目任意位置可生成Pdb文件,在添加QMAKE_LFLAGS_RELEASE += $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO后是可以生成Pdb文件,但是生成的Pdb文件会有异常,可参考“第一段 第三节 参数不全Pdb生成的Dump文件调试效果”。)**参考链接QT如何在Release编译下生成pdb文件
- 可更新Qt安装目录下对应编译器的msvc-desktop.conf文件,更新QMAKE_CFLAGS_RELEASE为:QMAKE_CFLAGS_RELEASE = $$QMAKE_CFLAGS_OPTIMIZE -MD -O2 -MD -Zi(如下图一),更新QMAKE_LFLAGS_RELEASE为:QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO /DEBUG(如下图二)。 ** (注:更新msvc-desktop.conf文件后,当前编译器所编译的所有项目都会生成Pdb文件,仅更新QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO /DEBUG也可生成Pdb文件,同样生成的Pdb文件会有异常,可参考“第一段 第三节 参数不全Pdb生成的Dump文件调试效果”。)**参考链接QT如何在Release编译下生成pdb文件
2.Dump文件不生产的情况
有些电脑中同一种状态不会崩溃,可能是被Qt事件循环接收处理了。
如本文中的情况,我个人在公司的电脑和我家的电脑运行就是只有一个生成Dump文件。
我个人测试(无法生成Dump文件的电脑),使用纯C++的代码可进入指定的Dump生成函数,只要进入Qt事件循环后就无法进入Dump生成函数,猜测是被Qt事件循环接收处理了
三、源码
Pro文件
QT+=core guigreaterThan(QT_MAJOR_VERSION,4):QT+=widgets CONFIG+=c++11####################1######################### ## 在“Pro”文件中添下方代码后可生成PDB文件(影响当前项目) ## 生成PDB PdbDumpTest.pdb PdbDumpTest.vc.pdb CONFIG+=force_debug_info ####################2######################### ## 生成PDB PdbDumpTest.pdb#QMAKE_CXXFLAGS_RELEASE+=$$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO#QMAKE_LFLAGS_RELEASE+=$$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO####################3######################### ## 在“构建设置”中“Build的步骤”中的“Additional arguments”添下方代码后可生成PDB文件(影响当前目录的当前项目) #"CONFIG += force_debug_info"####################4######################### ## 在下方对应目录文件中,参考如下更新文件的QMAKE_LFLAGS_RELEASE的赋值数据即可(影响所有项目) ## C:\Qt\Qt5.xx.xx\5.xx.xx\msvc2017_64\mkspecs\common\msvc-desktop.conf#QMAKE_CFLAGS_RELEASE=$$QMAKE_CFLAGS_OPTIMIZE (-MD-O2-MD-Zi)#QMAKE_LFLAGS_RELEASE=/INCREMENTAL:NO (/DEBUG)#You can make your code fail to compileifit uses deprecated APIs.#In order todoso,uncomment the following line.#DEFINES+=QT_DISABLE_DEPRECATED_BEFORE=0x060000# disables all the APIs deprecated before Qt6.0.0SOURCES+=\ main.cpp \ mainwindow.cpp HEADERS+=\ mainwindow.h FORMS+=\ mainwindow.ui#Default rulesfordeployment.qnx:target.path=/tmp/$${TARGET}/binelse:unix:!android:target.path=/opt/$${TARGET}/bin!isEmpty(target.path):INSTALLS+=targetmian.cpp
#include"mainwindow.h"#include<QApplication>#include<QDebug>#include<QDir>#include<QDateTime>#include<QSharedMemory>#include<QProcess>#include<QMessageBox>#ifdefQ_OS_WIN#include<Windows.h>#include<DbgHelp.h>#pragmacomment(lib,"dbghelp.lib")#endifLONG WINAPISystemExceptionCall(_EXCEPTION_POINTERS*ExceptionInfo){// 获取生成路径QString logFile=QApplication::applicationDirPath()+"/dump";// 判断路径是否存在if(!QDir(logFile).exists()){// 路径不存在则创建QDir().mkpath(logFile);}// 生成dump文件路径及名称QString dumpName=QString("%1/%2.dmp").arg(logFile).arg(QDateTime::currentDateTime().toString("yyyyMMdd-hh_mm_ss"));// 创建dump文件#if0// 使用CreateFile创建Dump文件,适用于包含详细参数的文件创建HANDLE hDumpFile=CreateFile(dumpName.toStdWString().c_str(),GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);#else// Pdb文件的配置参数(如文件显隐,编辑状态等)LPCREATEFILE2_EXTENDED_PARAMETERS fileParam=Q_NULLPTR;// 使用CreateFile2创建Dump文件,适用于普通文件创建,通常不需要其他配置参数使用该函数更为快捷HANDLE hDumpFile=CreateFile2(dumpName.toStdWString().c_str(),GENERIC_WRITE,FILE_SHARE_READ,CREATE_ALWAYS,fileParam);#endifif(hDumpFile!=INVALID_HANDLE_VALUE){MINIDUMP_EXCEPTION_INFORMATION dumpInfo;dumpInfo.ThreadId=GetCurrentThreadId();// 当前线程IddumpInfo.ExceptionPointers=ExceptionInfo;// 当前异常指针dumpInfo.ClientPointers=TRUE;// 写入Dump文件时,可以直接引用相关内存地址// 创建Dump文件MiniDumpWriteDump(GetCurrentProcess(),GetCurrentProcessId(),hDumpFile,MiniDumpWithDataSegs,&dumpInfo,Q_NULLPTR,Q_NULLPTR);// 关闭文件句柄CloseHandle(hDumpFile);}returnEXCEPTION_EXECUTE_HANDLER;}intmain(intargc,char*argv[]){#ifdefQ_OS_WIN//! 注册异常奔溃回调SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)SystemExceptionCall);#endifQApplicationa(argc,argv);MainWindow w;w.show();returna.exec();}MainWindow
mainwindow.h
#ifndefMAINWINDOW_H#defineMAINWINDOW_H#include<QMainWindow>QT_BEGIN_NAMESPACEnamespaceUi{classMainWindow;}QT_END_NAMESPACEclassMainWindow:publicQMainWindow{Q_OBJECTpublic:MainWindow(QWidget*parent=nullptr);~MainWindow();privateslots:voidon_btnCrash_clicked();private:Ui::MainWindow*ui;};#endif// MAINWINDOW_Hmainwindow.cpp
#include"mainwindow.h"#include"ui_mainwindow.h"#include<QDebug>MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(newUi::MainWindow){ui->setupUi(this);}MainWindow::~MainWindow(){deleteui;}voidMainWindow::on_btnCrash_clicked(){// qCritical("test");qDebug()<<"123456"<<__FUNCTION__;intb=10;inta=10/(b-10);qDebug()<<"123456"<<a;}Ui文件
<?xml version="1.0" encoding="UTF-8"?><uiversion="4.0"><class>MainWindow</class><widgetclass="QMainWindow"name="MainWindow"><propertyname="geometry"><rect><x>0</x><y>0</y><width>330</width><height>207</height></rect></property><propertyname="windowTitle"><string>MainWindow</string></property><widgetclass="QWidget"name="centralwidget"><layoutclass="QGridLayout"name="gridLayout"><itemrow="0"column="1"><spacername="verticalSpacer"><propertyname="orientation"><enum>Qt::Vertical</enum></property><propertyname="sizeHint"stdset="0"><size><width>20</width><height>52</height></size></property></spacer></item><itemrow="1"column="0"><spacername="horizontalSpacer"><propertyname="orientation"><enum>Qt::Horizontal</enum></property><propertyname="sizeHint"stdset="0"><size><width>110</width><height>20</height></size></property></spacer></item><itemrow="1"column="1"><widgetclass="QPushButton"name="btnCrash"><propertyname="text"><string>崩溃</string></property></widget></item><itemrow="1"column="2"><spacername="horizontalSpacer_2"><propertyname="orientation"><enum>Qt::Horizontal</enum></property><propertyname="sizeHint"stdset="0"><size><width>109</width><height>20</height></size></property></spacer></item><itemrow="2"column="1"><spacername="verticalSpacer_2"><propertyname="orientation"><enum>Qt::Vertical</enum></property><propertyname="sizeHint"stdset="0"><size><width>20</width><height>51</height></size></property></spacer></item></layout></widget><widgetclass="QMenuBar"name="menubar"><propertyname="geometry"><rect><x>0</x><y>0</y><width>330</width><height>23</height></rect></property></widget><widgetclass="QStatusBar"name="statusbar"/></widget><resources/><connections/></ui>总结
通过配置编辑项目,并使用系统提供的接口设置Dump文件生成函数,最后使用Vs调试代码即可。
友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 ^o^/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除