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开始打印。