使用Backtrace函数打印调用栈 - Debug居家必备
2013-10-24 15:44
495 查看
glibc提供了backtrace这个库函数,可以用来打印call stack。比如我们可以在程序中注册常见的一些signal,比如SIGSEGMENT, SIGPIPE,然后在这些信号的回调函数中,利用backtrace打印出call stack,这样debug就非常的方便。
backtrace的使用很简单,使用man手册中的Example代码即可,例如:
首先用backtrace,最多生成100层的call stack。然后用backtrace_symbols将backtrace返回的一堆地址翻译成函数名称。backtrace的返回值是具体生成了多少层的call stack,填充的btbuf是一个void *的数组,里面每个element都是一个void *,其实就是一个地址。
backtrace_symbols生成的字符串都是malloc出来的,但是不要最后一个一个的free,因为backtrace_symbols是根据backtrace给出的call stack层数,一次性的malloc出来一块内存来存放结果字符串的,所以,像上面代码一样,只需要在最后,free backtrace_symbols的返回指针就OK了。这一点backtrace的manual中也是特别提到的。
此外需要注意的是,使用backtrace来获取调用栈信息,在编译的时候需要加入:-rdynamic,这个option是传递给linker的,linker会将symbol放到.dydym table中,这样backtrace_symbols才能获取到地址对应的symbol。所以即使是使用了-g来编译程序,如果不使用-rdynamic的话,backtrace_symbols也找不到地址对应的symbol。这是backtrace系列函数的一个缺陷。不过有了地址也算是一个很大帮助了,毕竟可以使用gdb来找到对应的symbol。
backtrace的使用很简单,使用man手册中的Example代码即可,例如:
1 #include <execinfo.h> 2 #include <stdio.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <errno.h> 6 7 #define SIZE 100 8 9 void dump_stack() 10 { 11 int btnum = 0; 12 void *btbuf[SIZE]; 13 char **btstrings = NULL; 14 int i; 15 16 /* Get backtrace */ 17 btnum = backtrace(btbuf, SIZE); 18 btstrings = backtrace_symbols(btbuf, btnum); 19 if (btstrings == NULL) { 20 printf("Backtrace failed: %d:%s\n", errno, strerror(errno)); 21 } else { 22 printf("Backtraces, total %d items\n", btnum); 23 for (i = 0; i < btnum; i++) 24 printf("%s\n", btstrings[i]); 25 26 free(btstrings); 27 } 28 } 29 30 void start_working() 31 { 32 printf("Start working...\n"); 33 dump_stack(); 34 } 35 36 int main() 37 { 38 printf("Start backtracing...\n"); 39 start_working(); 40 return 0; 41 }
首先用backtrace,最多生成100层的call stack。然后用backtrace_symbols将backtrace返回的一堆地址翻译成函数名称。backtrace的返回值是具体生成了多少层的call stack,填充的btbuf是一个void *的数组,里面每个element都是一个void *,其实就是一个地址。
backtrace_symbols生成的字符串都是malloc出来的,但是不要最后一个一个的free,因为backtrace_symbols是根据backtrace给出的call stack层数,一次性的malloc出来一块内存来存放结果字符串的,所以,像上面代码一样,只需要在最后,free backtrace_symbols的返回指针就OK了。这一点backtrace的manual中也是特别提到的。
此外需要注意的是,使用backtrace来获取调用栈信息,在编译的时候需要加入:-rdynamic,这个option是传递给linker的,linker会将symbol放到.dydym table中,这样backtrace_symbols才能获取到地址对应的symbol。所以即使是使用了-g来编译程序,如果不使用-rdynamic的话,backtrace_symbols也找不到地址对应的symbol。这是backtrace系列函数的一个缺陷。不过有了地址也算是一个很大帮助了,毕竟可以使用gdb来找到对应的symbol。
相关文章推荐
- 使用Backtrace函数打印调用栈 - Debug居家必备
- 使用Backtrace函数打印调用栈 - Debug居家必备
- PHP中调试函数debug_backtrace的使用示例代码
- php 回溯函数打印 debug_print_backtrace
- 使用 backtrace 获得 Linux 函数调用栈
- PHP 使用 debug_print_backtrace() 或 debug_backtrace() 打印栈轨迹
- 利用backtrace和backtrace_symbols函数打印调用栈信息
- 利用backtrace和backtrace_symbols函数打印调用栈信息
- 利用backtrace和backtrace_symbols函数打印调用栈信息
- C++创建类必备的三个函数以及使用new所需要做的事
- go 获取函数调用者caller的函数名 打印堆栈runtime.Stack debug.Stack()
- 使用backtrace机制帮助debug信息
- GNU 的入口和出口配置函数的使用以及函数调用栈追踪
- GDB工具使用教程_函数调用栈(call stack)探密
- Linux 程序开发打印Debug 信息的使用技巧
- 利用backtrace和backtrace_symbols打印函数的调用关系
- 守护进程使用syslog函数打印信息(基于ARM-Linux)
- 在C/C++程序中打印当前函数调用栈
- Objextive-C入门学习1--使用NSLog函数在屏幕上打印HelloWorld
- PHP debug_backtrace() 函数