文章目录
一、软件奔溃捕获的意义
应用程序发布后,不能保证百分百没有bug并引发崩溃。因此,在出现崩溃的情况下需要记录崩溃详情并给用户弹出崩溃提示对话框,提示用户重启软件以及上报(上传)崩溃。
这样做意义是:
能保证软件在使用过程中发现的bug都能被收集起来,并根据崩溃详情修改bug,然后发布修复bug的版本。如果软件在使用过程中直接闪退没有任何提示,不仅用户体验不好,还无法获取崩溃的原因。之后更具用户反馈的口头描述来找bug就会非常头疼了。
二、Breakpad介绍
- breakpad简介
Breakpad是Google公司开发的开源多平台C++崩溃检测库。Breakpad可以捕获发布给用户的应用程序的崩溃,并记录软件崩溃的调试信息到“minidump”文件中。调试信息包括错误行号,报错详情,堆栈错误(stack traces)。软件崩溃时候把生成的“minidump”上传到自己的服务器上就可已方便的获取足够细致崩溃详情。
支持平台:
windows、linux、mac、ios、solaris、android ndk - breakpad实现原理简单了解
- 在不同平台下使用平台特有的函数以及方式实现异常捕获:
Windows:通过SetUnhandledExceptionFilter()设置崩溃回掉函数
Max OS:监听 Mach Exception Port 获取崩溃事件
Linux:监听 SIGILL SIGSEGV 等异常信号 获取崩溃事件 - MiniDump文件格式
minidump是由微软开发的崩溃记录文件格式。minidump为二进制文件,体积小。为了保持统一,breakpad在其他系统下也选择生成minidump文件。 - BreakPad工作原理示意图
示意图要表达的意思如下:
a. 包含了breakpad客户端(静态库)的应用程序在发布Release版本的时候。在编译的时候选择保留调试信息。
b. 使用Breakpad提供的dump_syms工具根据release版本程序生成“symbols文件”。“symbols文件”包括程序之前保留的调试信息。
c. 发布给用户的release版本程序发生崩溃后包含在程序内“breakpad客户端”会捕捉崩溃并生成“minidump文件”。
d. “minidump文件”被应用程序发送到你指定的服务器,或通过其他方式收到用户软件崩溃产生的“minidump文件”。
e. 收到“minidump文件”后,结合发布应用的所对应的 “symbols文件”,通过“minidump_stackwalk” 工具来转换生成文本格式的“stack trace 文件”。这个文件内的信息就是程序员可以直接阅读的崩溃堆栈详情。从而准确的找到触发崩溃的bug。
三、Qt工程中加入breakpad库的方法
breakpad可以先编译生成lib文件,然后在加入到自己的qt工程,也可以直接使用源码加入到自己的qt工程中。
为了方便在Qt中加入breakpad并且方便在多个平台编译,这里使用“源码添加breakpad库“的方式。
在Qt工程加入Breakpad的步骤如下:
- 下载源码:https://github.com/google/breakpad
- 把源码放置到自己工程目录里面,我这里使用的目录是:third_libs/breakpad/thirdparty
- 编写“breakpad.pri”文件用于在工程中引入所需要的breakpad源文件,把文件放置到和breakpad源码相同的目录。
- 编写多平台封装类。breakpad在不同系统中有不同的崩溃回调函数。为了实现跨平台使用breakpad,需要做一个封装类,然后对外提供一个唯一的接口。编写一个封装类为“BreakpadHandler”,放置在third_libs/breakpad/src目录中。
- 接着编写自己封装类的引入文件“breakpadsrc.pri”。并放置在third_libs/breakpad目录中。此配置文件还包括一些编译参数设置,从而包在各个平台的编译生成的release版本中包含调试信息。同时此文件相当于把整个breakpad相关的文件和配置整理到了一起。从而形成一个跨平台的breakpad模块。在自己的Qt工程中直接引入此模块,即可使用所有Breakpad的功能。
- 完成以上所有步骤,最终形成的目录结构如下图所示:
- 由于引入文件“breakpad.pri”、“breakpadsrc.pri”和“BreakpadHandler封装类”中的内容很长,因此不便在这里列出。请参考本文第九节中所列出的源码地址。源码中不仅集成了breakpad库,并且包含完整使用示例。
四、测试是否可以生成dump崩溃文件
为了演示上一节所制作的Brakpad库的使用方法。本文专门编写了一个示例工程“BreakpadDemo”。工程的编写过程如下:
- 使用Qt Creater新建一个工程,叫做“BreakpadDemo”
- 在工程的pro文件中引入之前编写好的brakpad模块
QT += core gui network //本例子包含网络上传代码
# link qBreakpad library
include($$PWD/third_libs/breakpad/breakpadsrc.pri)
- 在工程的main.cpp文件编写如下代码:
#include <QApplication>
#include "BreakpadHandler.h"
void crash() {
volatile int* a = (int*)(NULL); *a = 1; }
int main(int argc, char *argv[])
{
QApplication app (argc, argv);
//those settings are need by QStandardPaths and breakpad
QCoreApplication::