显示函数的调用关系是调试器的必备功能,如果我们在程序的运行中出现了崩溃的情况,通过函数的调用关系可以快速定位问题的根源,懂得函数调用关系的实现原理也可以扩充自己的知识面,在没有调试器的情况下,我们也可以自己来实现显示函数的调用关系。在我们自己动手写backtrace函数之前,先来看看glibc提供的backtrace函数的使用。代码如下:
#include <stdio.h> #define MAX_LEVEL 4 static void call2() int size=backtrace(buffer, MAX_LEVEL); for(i = 0; i < size; i++) return; static void call1() return; static void call() return; int main(int argc, char* argv[]) return 0; |
在此先讲解下backtrace()函数的使用:
int backtrace(void **buffer,int size)
该函数用来获取当前线程的调用堆栈,获取的信息将会被存放在buffer中,它是一个指针列表。参数 size 用来指定buffer中可以保存多少个void* 元素。函数返回值是实际获取的指针个数,最大不超过size大小,在buffer中的指针实际是从堆栈中获取的返回地址,每一个堆栈框架有一个返回地址。
接下来的任务就是编译运行了。
root@ubuntu:/home/shiyan# gcc -g -Wall sss.c -o p
root@ubuntu:/home/shiyan# ./p
输出结果为:
called by 0x8048440
called by 0x804847d
called by 0x804848a
called by 0x8048497