[QT]window下使用集成qBreakpad定位闪退的问题

前言

测试的同事反馈程序运行后挂机 1 天后突然闪退,需要找出问题并解决 bug,这里分享一下定位问题的经过。

经过查询资料,打算集成 Google Breakpad 的 Qt 封装库------qBreakpad到程序中,能实现程序奔溃时自动生成dump文件和pdb文件,再经过vs工具分析bug,找到问题。

使用步骤

  1. 下载源码,编译生成 lib。
  2. 在程序中 include 头文件,就可以在你的程序中集成了。
  3. 在程序崩溃时自动生成 dump 文件。
  4. 利用工具分析 dump 文件。

一、源码准备

1. 下载 Breakpad 源码

https://github.com/google/breakpad

2. 下载 qBreakpad 源码

https://github.com/buzzySmile/qBreakpad.git

3. 下载 LSS 源码

https://github.com/plexinc/breakpad-lss/tree/master

(只需要 linux_syscall_support.h 这个 .h 文件就可以)

或者直接用现成我集成好的:包含了 qBreakpad、Breakpad、LSS 完整的工程。

bash 复制代码
网盘链接: https://pan.baidu.com/s/1iCmk_wQpU-ZPBn1rGTwQXg 
提取码: ea85

如果用网盘的代码下面这一步(第4点)可以忽略。

4.将 qBreakpad、breakpad、lss 源码下载完成后解压后,把 breakpad、lss 放入 qBreakpad 的 third_party 目录下,如下:

二、qBreakpad工程介绍

在qBreakpad源码目录下,使用QtCreator打开qBreakpad.pro工程,如下:

demo工程下,有2个演示程序program和reporter,分别实现了演示生成dump文件、上报dump文件的功能。

handler为静态库工程,该工程封装了Breakpad,直接编译此工程,可生成qBreakpad.lib。

tests为测试工程。

三、编译生成qBreakpad.lib

1.在Debug、Release模式下,编译handler工程,生成2个版本的qBreakpad.lib静态库。由于我只需要在Release模式下调试,下面就只演示Release模式下的编译过程。

编译后生成的 .lib 如下图:

说明:Release模式不会自动生成pdb文件,这里只需要拿到对应的
.lib文件即可!

四、在要调试的程序中调用qBreakpad

1.在工程目录下建立qbreakpadlib目录。

2.新建qbreakpadlib\lib\release目录,把release版qBreakpad.lib拷贝至此。

3.再将下图的2个头文件以及singleton文件夹一起拷贝到include下即可。此时qbreakpadlib的目录结构,如下:

4.在项目的.pro文件中,添加如下内容:

cpp 复制代码
############ for qBreakpad ############
# qBreakpad中需要使用到network模块
QT += network

# 启用多线程、异常、RTTI、STL支持
CONFIG += thread exceptions rtti stl

# without c++11 & AppKit library compiler can't solve address for symbols
CONFIG += c++11
macx: LIBS += -framework AppKit

# 配置头文件搜索路径和链接库路径
win32:CONFIG(release, debug|release): {
LIBS += -L$$PWD/qbreakpadlib/lib/release/ -lqBreakpad
DEPENDPATH += $$PWD/qbreakpadlib/lib/release
} 
else:win32:CONFIG(debug, debug|release): {
LIBS += -L$$PWD/qbreakpadlib/lib/debug/ -lqBreakpad
DEPENDPATH += $$PWD/qbreakpadlib/lib/debug
}

INCLUDEPATH += $$PWD/qbreakpadlib/include

############ for qBreakpad ############

5.然后在main.cpp中添加调用代码,如下:

cpp 复制代码
#include <QApplication>
#include "QBreakpadHandler.h"//添加头文件
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QBreakpadInstance.setDumpPath("crashes");    // 设置生成dump文件路径
		...........
}

五、生成Release pdb文件

之前说过在release模式下,不会生成pdb文件,有这个pdb文件会更容易定位问题

所以,需要在qBreakpadTest.pro文件中,添加如下内容,让release版程序带上调试信息:

cpp 复制代码
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO

win系统下,程序的调试信息,是在单独的pdb文件中;在其他linux、mac等系统下,程序的调试信息就包含在程序本体内部,所以带调试信息的程序一般比不带调试信息的大。

清除以后qmake,再次编译,可以看到,已经生成了"程序名.pdb"

六、测试:

故意写了一个会引起程序奔溃的语句

生成dump文件

特别注意

如果使用MinGW编译程序,无法生成pdb文件,这点需要注意一下。必须使用MSVC编译,方可生成pdb文件。

目前我们已经生成了程序的pdb调试信息文件,并且程序执行过程中发生崩溃,也可以自动记录dump文件,这2个文件已经具备,接下来,我们看看如何利用他们定位到bug所在位置。

七、使用VS进行调试

我这里使用VS 2017,来进行如下的操作。

1.打开dump文件

Vs文件菜单下,选择"打开"->"文件",或者直接拖拽。

2.找到dump文件,并打开。

3.设置pdb文件路径

接下来,点击"设置符号路径",点击"+"号,添加pdb文件路径,之后,"确定"。如下:

选择:使用仅限本机进行调试

看到它自己定位到出现bug的位置了。

注意:生成bug时候的代码必须和分析bug时候的代码一样,不然工具就会找不到出现bug的位置

引用

Qt Windows系统使用QBreakpad实战

Qt qBreakPad使用(windows)