嵌入式

编程与应用
posts - 14, comments - 1, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

打印函数调用堆栈并具体位置

Posted on 2012-04-23 16:34 陈显锋 阅读(2022) 评论(0)  编辑 收藏 引用 所属分类: 技术交流
 1 #include <stdio.h>
 2 #include <execinfo.h>
 3 
 4 void print_trace(void);
 5 void funcC()
 6         {    /* 打印调用堆栈,看看谁调用了本函数 */
 7     print_trace();
 8 }
 9 void funcB()
10  {
11      funcC();
12  }
13  void funcA()
14  {
15      funcB();
16  }
17  int main (void)
18  {
19      funcA();
20      return 0;
21  }
22  void print_trace(void)
23  {
24      int i;
25      const int MAX_CALLSTACK_DEPTH = 32;    /* 需要打印堆栈的最大深度 */
26      void *traceback[MAX_CALLSTACK_DEPTH];  /* 用来存储调用堆栈中的地址 */
27     /* 利用 addr2line 命令可以打印出一个函数地址所在的源代码位置
28      * 调用格式为: addr2line -f -e /tmp/a.out 0x400618
29      * 使用前,源代码编译时要加上 -rdynamic -g 选项
30      */
31     char cmd[512= "addr2line -f -e ";
32     char *prog = cmd + strlen(cmd);
33     /* 得到当前可执行程序的路径和文件名 */
34     int r = readlink("/proc/self/exe",prog,sizeof(cmd)-(prog-cmd)-1);
35     /* popen会fork出一个子进程来调用/bin/sh, 并执行cmd字符串中的命令,
36      * 同时,会创建一个管道,由于参数是'w', 管道将与标准输入相连接,
37      * 并返回一个FILE的指针fp指向所创建的管道,以后只要用fp往管理里写任何内容,
38      * 内容都会被送往到标准输入,
39      * 在下面的代码中,会将调用堆栈中的函数地址写入管道中,
40      * addr2line程序会从标准输入中得到该函数地址,然后根据地址打印出源代码位置和函数名。
41      */
42     FILE *fp = popen(cmd, "w");
43  /* 得到当前调用堆栈中的所有函数地址,放到traceback数组中 */
44     int depth = backtrace(traceback, MAX_CALLSTACK_DEPTH);
45     for (i = 0; i < depth; i++)
46     {
47         /* 得到调用堆栈中的函数的地址,然后将地址发送给 addr2line */
48         fprintf(fp, "%p/n", traceback[i]);
49         /* addr2line 命令在收到地址后,会将函数地址所在的源代码位置打印到标准输出 */
50     }
51     fclose(fp);
52 }

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理