Linux 下打印程序调用栈callstack

Linux下打印程序调用栈callstack

1. Java代码中打印堆栈

Java代码打印堆栈比较简单, 堆栈信息获取和输出,都可以通过Throwable类的方法实现。目前通用的做法是在java进程出现需要注意的异常时,打印堆栈,然后再决定退出或挽救。通常的方法是使用exception的printStackTrace()方法:

1 try {
2 ...
3 } catch (RemoteException e) {
4 
5 e.printStackTrace();
6 ...
7 }

当然也可以只打印堆栈不退出,这样就比较方便分析代码的动态运行情况。Java代码中插入堆栈打印的方法如下:

1 Log.d(TAG,Log.getStackTraceString(new Throwable()));

 

2. C++代码中打印堆栈

2.1 通过捕获异常

参考文章:

https://stackoverflow.com/questions/3899870/print-call-stack-in-c-or-c/26529030

https://blog.csdn.net/Zhanglin_Wu/article/details/109333908?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_aggregation-3-109333908.pc_agg_rank_aggregation&utm_term=call+stack%E5%9C%A8c%2B%2B%E4%B8%AD&spm=1000.2123.3001.4430

在Linux中运行的C++程序,如果抛出的异常(exception)未被捕获,则可以用一些方法强行打印出调用栈(callstack),以下仅为示例:

 1 #include <exception>
 2 #include <iostream>
 3 #include <string>
 4 
 5 #include <execinfo.h>
 6 #include <unistd.h>
 7 
 8 using namespace std;
 9 
10 void print_trace(void) {
11     size_t i, size;
12     enum Constexpr { MAX_SIZE = 1024 };
13     void *array[MAX_SIZE];
14     
15     size = backtrace(array, MAX_SIZE);
16     backtrace_symbols_fd(array, size, STDOUT_FILENO);
17     
18     puts("");
19 }
20 
21 int main(int argc, char* argv[])
22 {
23     std::set_terminate([](){
24         cout << "Unhandled exception with callstack:" << std::endl;
25         print_trace();
26         std::abort();
27     });
28 
29     throw runtime_error("This is an exception");
30 
31     return 0;
32 }

 

2.2 直接打印堆栈

C++也是支持异常处理的,异常处理库中,已经包含了获取backtrace的接口,Android也是利用这个接口来打印堆栈信息的。在Android的C++中,已经集成了一个工具类CallStack,在libutils.so中。使用方法:

1 #include <utils/CallStack.h>
2 
3 ...
4 CallStack stack;
5 stack.update();
6 stack.dump();

使用方式比较简单。目前Andoid4.2版本已经将相关信息解析的很到位,符号表查找,demangle,偏移位置校正都做好了。

3. C代码中打印堆栈

下面代码只能用在 usespace,kernel space需要重新去封装:

 1 #include <execinfo.h>
 2 
 3 void kmj_print_trace (void)
 4 {
 5     void *array[16];
 6     size_t size;
 7     char **strings;
 8     size_t i;
 9 
10     size = backtrace (array, 16);
11     strings = (char **)backtrace_symbols (array, size);
12     printf("[dump_stack]print_trace[pid=%d]\n", getpid());
13 
14     for (i = 0; i < size; i++)
15     {
16         printf("%s\n", strings[i]);
17     }
18     free (strings);
19 }

 

kernel space:

在Linux内核调试中,经常用到的打印函数调用堆栈的方法非常简单,只需在需要查看堆栈的函数中加入:

dump_stack();或 __backtrace();即可。

dump_stack() 在 ~/kernel/lib/Dump_stack.c中定义:

1 void dump_stack(void)
2 {
3      printk(KERN_NOTICE  "This architecture does not implement dump_stack()/n");
4 }

__backtrace() 的定义在~/kernel/arch/arm/lib/backtrace.S中

1 ENTRY(__backtrace)
2   mov r1, #0x10
3   mov r0, fp

 

参考文章:

https://www.cnblogs.com/catgatp/p/6363505.html

 

posted @ 2022-01-15 15:33  西门吹雪~~~  阅读(2269)  评论(0编辑  收藏  举报