作者 | Waleon

来源 | 高效程序员

Breakpad 是 Google 用 C++ 编写的一个开源、跨平台的崩溃报告系统,它支持 Windows、Linux 和 macOS,并提供了一个上传器,可以在进程崩溃时向一个配置好的 URL 提交 minidump 文件。

目前,有很多大型项目都在使用 Breakpad,例如:Google Chrome、Firefox、Google Picasa、Camino、Google Earth 等。

  • 主页:https://chromium.googlesource.com/breakpad/breakpad/

  • 文档:https://chromium.googlesource.com/breakpad/breakpad/+/HEAD/docs

  • GitHub 地址:https://github.com/google/breakpad

工作原理

BreakPad 工作原理:

其中,包含了三个主要组件:

  • Breakpad client:是一个库(即:libbreakpad_client.a),将来要集成到我们的程序中。用于写 minidump 文件,捕获当前线程的状态,以及可执行文件/共享库的标识。

  • Breakpad 符号转储工具:是一个程序(即:dump_syms),用于读取由编译器产生的调试信息,并以 Breakpad 自己的格式生成一个符号文件。

  • Breakpad minidump 处理器:是一个程序(即:minidump_stackwalk),用于读取 minidump 文件和符号文件,并生成一个可读的 C/C++ 堆栈跟踪。

编译安装

  1. 下载 Breakpad 源码;

  2. 由于 Breakpad 依赖于 LSS,所以还需要下载它(地址:https://github.com/adelshokhy112/linux-syscall-support);

  3. 将 LSS 中的 linux_syscall_support.h 文件放至breakpad/src/third_party/lss/ 目录下;

  4. 编译 Breakpad,步骤非常简单:

$ cd breakpad
$ ./configure && make
$ make
$ sudo make install

成功之后,会生成 libbreakpad_client.a 库文件,以及dump_syms、minidump_stackwalk 等程序。

将 Breakpad 集成到程序中

和其他第三方库的用法一样,要将 Breakpad 集成到程序中,先要链接生成的库 libbreakpad_client.a,并设置包含路径为breakpad/src/,接下来就可以 include 头文件了。

为了生成 mindump 文件,我们需要实例化一个ExceptionHandler 对象,并提供一个存储 mindump 的路径,以及一个回调函数来接收关于已写入的 mindump 的信息:

#include "client/linux/handler/exception_handler.h"
#include <iostream>static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,void* context,bool succeeded)
{std::cout << "Dump path:" << descriptor.path() << std::endl;return succeeded;
}void crash()
{int* a = nullptr;*a = 1;
}int main(int argc, char* argv[])
{google_breakpad::MinidumpDescriptor descriptor("/tmp");google_breakpad::ExceptionHandler eh(descriptor, nullptr, dumpCallback, nullptr, true, -1);crash();return 0;
}

编译运行这个程序,会在 /tmp/ 目录下生成一个 minidump 文件,并在退出之前打印该文件的路径。

注意:在使用 Breakpad 时,需要目标程序内包含调试信息,这样dump_syms 工具才能从中解析出调试符号。而在默认情况下,Release 模式编译的程序是并不包含调试信息,若想包含,需要在编译程序时添加 -g 选项。

生成可读的堆栈跟踪

带调试信息的目标程序有了,minidump 文件有了,dump_syms 和minidump_stackwalk 等工具也有了,现在要做的就是生成有用的堆栈跟踪信息了!

1. 生成符号文件

Breakpad 要求我们将目标程序中的调试符号转换为文本格式的符号文件,这一步需要通过 dump_syms 工具来完成。

假设,我们的程序名为 test,执行以下命令,便会生成一个名为 test.sym 的符号文件:

$ dump_syms ./test > test.sym

2. 将符号文件放在特定目录下

为了使用这些符号,需要将生成的符号文件放在特定的目录结构中:

查看符号文件,第一行包含了生成目录结构所需的信息:

$ head -n1 test.sym
MODULE Linux x86_64 95E20E34BE203CB093B675D606A7D7D20 test

创建以上目录结构,并将符号文件移动到该路径下:

$ mkdir -p ./symbols/test/95E20E34BE203CB093B675D606A7D7D20
$ mv test.sym ./symbols/test/95E20E34BE203CB093B675D606A7D7D20/

3. 生成堆栈跟踪信息

当一切准备就绪,minidump_stackwalk 工具就派上用场了。

只需将 mindump 文件和符号路径作为命令行参数传递给它,便能生成堆栈跟踪信息了。为了便于分析,可以将输出重定向至文件中:

$ minidump_stackwalk /tmp/48596758-1d7a-4318-15edb4af-a9186ad7.dmp ./symbols > error.log

定位 Crash 所在位置

打开 error.log,搜索关键字“crashed”,一般与它最接近的一行,就是发生崩溃时程序的堆栈信息:

可以很清楚地看到,崩溃发生在 main.cpp 的第 16 行。

查看我们的测试程序,与预期结果一样:

至此,Crash 所在位置已经准确地定位到了,赶紧抓紧时间修改吧!

将上述过程脚本化

由于以上过程会经常执行,可以将其做成自动化脚本,不仅可有效防止步骤命令的遗忘,而且极大的加快了操作速度。

新建一个脚本 dumptool.sh,内容如下:

#!/bin/bashif [ $# != 3 ] ; then
echo "USAGE: $0 TARGET_NAME DMP_NAME OUTPUT_NAME"
echo " e.g.: $0 test 48596758-1d7a-4318-15edb4af-a9186ad7.dmp error.log"
exit 1;
fi #获取输入参数
target_file_name=$1
dmp_file_name=$2
output_file_name=$3getSymbol() {echo "@getSymbol: start get symbol"dump\_syms ./$target_file_name > $target_file_name'.sym'
}getStackTrace() {echo "@getStackTrace: start get StackTrace"sym_file_name=$target_file_name'.sym'#获取符号文件中的第一行line1=`head -n1 $sym_file_name`#从第一行字符串中获取版本号OIFS=$IFS; IFS=" "; set -- $line1; aa=$1;bb=$2;cc=$3;dd=$4; IFS=$OIFS version_number=$dd#创建特定的目录结构,并将符号文件移进去mkdir -p ./symbols/$target_file_name/$version_numbermv $sym_file_name ./symbols/$target_file_name/$version_number#将堆栈跟踪信息重定向到文件中minidump_stackwalk $dmp_file_name ./symbols > $output_file_name
}main() {getSymbol if [ $? == 0 ] then getStackTracefi
}#运行main
main

使用比较简单,先为脚本增加可执行权限:

$ chmod +x ./dump_tool.sh

然后执行下述命令,将二进制文件、minidump 文件、输出日志文件作为参数传递给它:

$ ./dumptool.sh ./test /tmp/48596758-1d7a-4318-15edb4af-a9186ad7.dmp error.log

完成之后,所有的堆栈跟踪信息就会被输出到 error.log 文件中了。

很好用吧,学会这个绝招,让 C++ 崩溃无处可逃!

☞OPPO 40万年薪招应届生,狂揽芯片人才;恶意差评小米新手机,一用户被判赔3万元;谷歌开源全同态加密通用转译器|极客头条☞乔布斯居然是这样面试我的,你能挺到哪一步?
☞Android 杀后台太狠,谷歌:看不下去了,势必要揪出“凶手”!

学会这个绝招,让 C++ 崩溃无处可逃!相关推荐

  1. aspose.words 操作word插入空白页_让 “空白页”无处可逃,消除你的烦恼

    --word2016系列教程之"空白页删除" 在word编辑文档时,经常会遇到在文档末尾出现一页空白页,尤其是在表格结束后,也会出现这样一页,你绞尽脑汁,用"BackSp ...

  2. 移动营销的魔力:让你的客户无处可逃(附赠2012移动营销百问百答手册)

    <移动营销的魔力:让你的客户无处可逃>(附赠2012移动营销百问百答手册) 基本信息 作者: (美)克鲁姆(Krum, C.) [作译者介绍] 译者: 唐兴通 出版社:电子工业出版社 IS ...

  3. 无处可逃:罗兴亚人的困境恶化 | 经济学人早报精选20210826

    文 / 王不留(微信公众号:考研英语笔记) 2021年8月26号的早晨,来杯"资讯咖啡",提神解困. 文章选自2021年8月26号的<The Economist Espres ...

  4. android揪出内存泄漏元凶 让它无处可逃

    揪出内存泄漏元凶  让它无处可逃 好久没更新技术博客了,这几天积攒了很多技术问题,今天要说的是内存泄漏定位和解决.在新公司做了一个多月了,接手前面的代码,多多少少都会有些坑,但是内存泄漏这种问题一直以 ...

  5. 十年 | 在Java开发做了10年后,才学会此绝招,用于颠覆Java应用

    Hi ! 我是小小,今天开始本周的第三篇,着重讲解 Java 的反射与代理. 什么是反射 一般情况下,需要一个功能的前提是遇到了什么问题,先列举一些问题,再通过反射是如何解决这些问题.普通开发人员工作 ...

  6. 黑人是晒黑的吗_当您是互联网上的黑人时,无处可逃

    黑人是晒黑的吗 By A. Rochaun Meadows-Fernandez 作者:A.Rochaun Meadows-Fernandez There were no words to descri ...

  7. deepfake 图片_DeepFake克星来了!简单2步算法,造假图像无处可逃

      新智元报道   来源:IEEE Spectrum 编辑:金磊 [新智元导读]DeepFake最近成了热点,也带来不少担忧.近期,针对DeepFake可能带来的负面影响,研究人员开发了一个基于神经网 ...

  8. FPGA中亚稳态——让你无处可逃

    1. 应用背景 1.1         亚稳态发生原因 在FPGA系统中,如果数据传输中不满足触发器的Tsu和Th不满足,或者复位过程中复位信号的释放相对于有效时钟沿的恢复时间(recovery ti ...

  9. 知物由学 |“网状世界”下,无处可逃的信息安全

    欢迎访问网易云社区,了解更多网易技术产品运营经验. "知物由学"是网易云易盾打造的一个品牌栏目,词语出自汉·王充<论衡·实知>.人,能力有高下之分,学习才知道事物的道理 ...

最新文章

  1. Springboot的slf4j的配置文件模板
  2. uva 10047 the monocyle (四维bfs)
  3. 数据库SQL优化大总结之 百万级数据库优化方案(转)
  4. java语言错误的是解释运行的_Java基础知识测试__A卷_答案
  5. 在.net中创建外接程序
  6. Linux之seq命令
  7. java 1.7 环境变量_安装JDK1.8之后又安装1.7出现的环境变量问题
  8. 吉米多维奇数学分析习题集--习题1380(用隐函数求导计算泰勒展开式)
  9. 现代城市生态与环境学
  10. 真分数化简为最简分数(6/8==3/4)
  11. 解决2020R2,2022R1等版本的SCDM无法编辑草图尺寸的问题
  12. 华盛顿大学计算机专业gpa,华盛顿大学计算机专业基本信息全盘点 学习来这里就对了...
  13. python中死循环有用吗_Python里是否存在死循环
  14. 游戏研发学习路线(思维导图)
  15. 经验分享:半桥电路的工作原理及注意问题(转载)
  16. 静态页面 常见问题 margin-top塌陷、padding把盒子撑大
  17. 如何绘制业务架构图 — 1. 概述
  18. Maven - 客户端 Nexus 配置
  19. 液体之火,酒,写的真好 ~~
  20. layui数据表格显示序号

热门文章

  1. GTK+图形化应用程序开发学习笔记(一)—概述
  2. JS实现图片翻书效果
  3. 敏捷开发用户故事系列之七:用户故事与MVC
  4. +号的用法(3+5+“8”与“3”+5+8相同吗)
  5. 第四周—扒开系统调用的“三层皮”
  6. Android中插件开发篇之----类加载器
  7. 链表(创建,插入,删除和打印输出
  8. Castle Team宣布Castle将与ASP.NET MVC整合
  9. [C++] 栈 和 队列
  10. mysql-5.6.14.tar.gz_CentOS 6.4下编译安装MySQL 5.6.14