Backward-cpp: Segmentation fault时打印backtrace

原文地址:https://www.cnblogs.com/liqinglucky/p/backward-cpp.html

一 介绍

项目地址:backward-cpp

Backward是由C++写的库,它能打印栈的backtrace。

程序异常崩溃是会出现提示:

Segmentation fault (core dumped)

利用Backward可以在此时自动打印出栈的backtrace信息。

当然使用时需要程序带符号表编译才能打印出代码段信息。

项目源码就两个文件,集成进自己的程序也很方便。如果只是用在打印Segmentation fault的backtrace,并不需要在自己项目代码中调用Backward-cpp里的函数,只需要将Backward-cpp作为子目录添加进项目编译就可以实现。

类似项目还有:Segmentation fault时打印栈

二 编译

1 编译环境

Ubuntu 20.04.4 LTS

2 编译

官方文档:README

下载源码

git clone https://github.com/bombela/backward-cpp

主要源文件

// backward库本身就这两个文件,非常简单。
backward-cpp# ls
backward.cpp
backward.hpp

// 测试backward的代码文件
backward-cpp/test# ls
rectrace.cpp
select_signals.cpp
stacktrace.cpp
suicide.cpp
test.cpp

编译源码

//cmake编译
backward-cpp# mkdir build
backward-cpp/build# cmake ..
-- Configuring done
-- Generating done

backward-cpp/build# make
[100%] Linking CXX executable test_select_signals
[100%] Built target test_select_signals

编译生成

backward-cpp/build# ls
// 由backward.cpp,backward.hpp生成的静态库文件
libbackward.a

// 由test目录生成的可执行文件
test_rectrace
test_select_signals
test_stacktrace
test_suicide
test_test

三 运行测试

编译完成后可以运行测试用的可执行文件

backward-cpp/build# ./test_stacktrace
-- running test case: smalltrace
Stack trace (most recent call last):
#12   Object "", at 0xffffffffffffffff, in
#11   Object "/backward-cpp/build/test_stacktrace", at 0x561dd7070dad, in _start
#10   Source "../csu/libc-start.c", line 308, in __libc_start_main
#9    Source "/backward-cpp/test/_test_main.cpp", line 227, in main
      > 227:     if (run_test(test)) {
        228:       printf("-- test case success: %s\n", test.name);

#8    Source "/backward-cpp/test/_test_main.cpp", line 140, in run_test
      > 140:     exit(static_cast<int>(test.run()));
#7    Source "/backward-cpp/test/test.hpp", line 92, in run
         90:   TestStatus run() {
         91:     try {
      >  92:       do_test();
#6    Source "/backward-cpp/test/stacktrace.cpp", line 54, in do_test
         53:   StackTrace st;
      >  54:   a(st);
         55:
         56:   printer.print(st, std::cout);
         57: }
#5    Source "/backward-cpp/test/stacktrace.cpp", line 48, in a
         46: void b(StackTrace &st) { return c(st); }
         47:
      >  48: NOINLINE void a(StackTrace &st) { return b(st); }
         49:
         50: TEST(smalltrace) {
         51:   Printer printer;
#4    Source "/backward-cpp/test/stacktrace.cpp", line 46, in b
      >  46: void b(StackTrace &st) { return c(st); }
#3    Source "/backward-cpp/test/stacktrace.cpp", line 44, in c
      >  44: void c(StackTrace &st) { return d(st); }
#2    Source "/backward-cpp/test/stacktrace.cpp", line 42, in d
      >  42: void d(StackTrace &st) { st.load_here(); }
#1    Source "/backward-cpp/backward.hpp", line 878, in load_here
      > 878:     size_t trace_cnt = details::unwind(callback(*this), depth);
#0    Source "/backward-cpp/backward.hpp", line 860, in unwind<backward::StackTraceImpl<backward::system_tag::linux_tag>::callback>
      > 860:   return unwinder(f, depth);
-- test case success: smalltrace               <<< _test_main.cpp
-- tests passing: 2/2 (100%)

这里已经打印出了栈的backtrace。

代码分析

结合stacktrace.cpp里对应代码分析上面的backtrace。函数调用关系为:

flowchart TD subgraph 函数调用关系 a1[_test_main.cpp:227 'main'] a2[_test_main.cpp:140 'run_test'] a3[stacktrace.cpp:54 'do_test'] a4[stacktrace.cpp:48 'a'] a5[stacktrace.cpp:46 'b'] a6[stacktrace.cpp:44 'c'] a7[stacktrace.cpp:42 'd'] a8[backward.hpp:878 'st.load_here'] a9[打印调用栈] a1-->a2-->a3-->a4-->a5-->a6-->a7-->a8-->a9 end

所以打印的backtrace就是函数调用的层级关系,从main函数开始一直调用到 st.load_here()进入backward.hpp开始打印。

参考

使用教程:一个漂亮的C ++堆栈跟踪打印器-backward-cpp - 简书 (jianshu.com)

posted @ 2023-02-25 14:32  liqinglucky  阅读(488)  评论(0编辑  收藏  举报