概述
C/C++打印runtime的调用栈
方案1: bombela/backward-cpp
这是在github上找到的一个很好的方案,可以实现异常捕捉以及runtime的stack展示,我做了一个更好一点的封装,只需要include头文件就可以了。
具体的链接参见这里
需要注意的是,最好在编译的时候,使用debug模式,同时需要链接到系统的dl和bfd两个库。
一个简单的例子:
step1: 安装依赖:
apt-get install binutils-dev
step2: 编译源码:
make && ./backtrace_benchmark
step3: 结果展示
Registering backtrace service successful
=========== show_stack_snapshot_at_runtime===========
Stack trace (most recent call last):
#7 Object "", at 0xffffffffffffffff, in
#6 Object "backtrace_benchmark", at 0x5568e64a38d9, in _start
#5 Source "/build/glibc-S9d2JN/glibc-2.27/csu/../csu/libc-start.c", line 310, in __libc_start_main
#4 Source "example/backward_test.cc", line 18, in main
15: }; // namespace
16: int main(void)
17: {
> 18: show_stack_snapshot_at_runtime();
19: show_exception();
20: return 0;
21: }
#3 Source "example/backward_test.cc", line 8, in (anonymous namespace)::show_stack_snapshot_at_runtime()
5: void show_stack_snapshot_at_runtime()
6: {
7: std::cout << "=========== show_stack_snapshot_at_runtime===========" << std::endl;
> 8: newplan_toolkit::BackTraceService::show_stack_snapshot();
9: }
10: void show_exception()
11: {
#2 Source "example/../backtrace_service.h", line 23, in newplan_toolkit::BackTraceService::show_stack_snapshot()
20: static void show_stack_snapshot()
21: {
22: backward::StackTrace st;
> 23: st.load_here(128);
24: backward::Printer p;
25: p.print(st);
26: }
#1 Source "example/../3rd_party/backward/backward.hpp", line 869, in backward::StackTraceImpl<backward::system_tag::linux_tag>::load_here(unsigned long, void*, void*)
866: return 0;
867: }
868: _stacktrace.resize(depth);
> 869: size_t trace_cnt = details::unwind(callback(*this), depth);
870: _stacktrace.resize(trace_cnt);
871: skip_n_firsts(0);
872: return size();
#0 Source "example/../3rd_party/backward/backward.hpp", line 851, in unsigned long backward::details::unwind<backward::StackTraceImpl<backward::system_tag::linux_tag>::callback>(backward::StackTraceImpl<backward::system_tag::linux_tag>::callback, unsigned long)
849: template <typename F> size_t unwind(F f, size_t depth) {
850: Unwinder<F> unwinder;
> 851: return unwinder(f, depth);
852: }
853:
854: } // namespace details
===========show_exception===========
terminate called after throwing an instance of 'char const*'
Stack trace (most recent call last):
#11 Object "", at 0xffffffffffffffff, in
#10 Object "backtrace_benchmark", at 0x5568e64a38d9, in _start
#9 Source "/build/glibc-S9d2JN/glibc-2.27/csu/../csu/libc-start.c", line 310, in __libc_start_main [0x7ff391249bf6]
#8 Source "example/backward_test.cc", line 19, in main [0x5568e64a3a7b]
16: int main(void)
17: {
18: show_stack_snapshot_at_runtime();
> 19: show_exception();
20: return 0;
21: }
#7 Source "example/backward_test.cc", line 13, in (anonymous namespace)::show_exception() [0x5568e64a3a6a]
10: void show_exception()
11: {
12: std::cout << "===========show_exception===========" << std::endl;
> 13: newplan_toolkit::execption_test();
14: }
15: }; // namespace
16: int main(void)
#6 Source "example/../backtrace_service.h", line 73, in newplan_toolkit::execption_test(int, int) [0x5568e64a39f5]
70: {
71: if (b == 0)
72: {
> 73: throw "Division by zero condition!";
74: }
75: while (1)
76: a = a + 2; // normally, the process would stuck here until a signal ctrl+c
#5 Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7ff3918c3d53, in __cxa_throw
#4 Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7ff3918c3b20, in std::terminate()
#3 Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7ff3918c3ae5, in std::rethrow_exception(std::__exception_ptr::exception_ptr)
#2 Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7ff3918bd956, in
#1 Source "/build/glibc-S9d2JN/glibc-2.27/stdlib/abort.c", line 79, in __GI_abort [0x7ff391268920]
#0 Source "/build/glibc-S9d2JN/glibc-2.27/signal/../sysdeps/unix/sysv/linux/raise.c", line 51, in __GI_raise [0x7ff391266fb7]
Aborted (Signal sent by tkill() 32001 1001)
fish: Job 1, './backtrace_benchmark' terminated by signal SIGABRT (Abort)
方案2: boost::stacktrace::stacktrace
一个简单的例子:
安装依赖
sudo apt-get install libboost-stacktrace-dev
源码boost_stacktrace.cpp
#include <iostream>
#define BOOST_STACKTRACE_USE_ADDR2LINE
#include <boost/stacktrace.hpp>
void my_func_2(void) {
std::cout << boost::stacktrace::stacktrace() << std::endl;
}
void my_func_1(double f) {
(void)f;
my_func_2();
}
void my_func_1(int i) {
(void)i;
my_func_2();
}
int main(int argc, char **argv) {
long long unsigned int n;
if (argc > 1) {
n = strtoul(argv[1], NULL, 0);
} else {
n = 1;
}
for (long long unsigned int i = 0; i < n; ++i) {
my_func_1(1); // line 28
my_func_1(2.0); // line 29
}
}
编译
g++ -fno-pie -ggdb3 -O0 -no-pie -o boost_stacktrace.out -std=c++11
-Wall -Wextra -pedantic-errors boost_stacktrace.cpp -ldl
运行
./boost_stacktrace.out
结果如下:
0# my_func_2() at /usr/include/boost/stacktrace/stacktrace.hpp:129
1# my_func_1(int) at /root/example/boost_strace.cc:18
2# main at /root/example/boost_strace.cc:29 (discriminator 2)
3# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
4# _start in ./boost_stacktrace.out
0# my_func_2() at /usr/include/boost/stacktrace/stacktrace.hpp:129
1# my_func_1(double) at /root/example/boost_strace.cc:13
2# main at /root/example/boost_strace.cc:27 (discriminator 2)
3# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
4# _start in ./boost_stacktrace.out
参考资料
https://stackoverflow.com/questions/3899870/print-call-stack-in-c-or-c
https://github.com/bombela/backward-cpp
最后
以上就是端庄猫咪为你收集整理的C++打印调用栈的全部内容,希望文章能够帮你解决C++打印调用栈所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复