免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 11117 | 回复: 11
打印 上一主题 下一主题

打印函数调用栈和入参是怎么实现的?(就是gdb中bt命令的功能) [复制链接]

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-05-19 09:35 |只看该作者 |倒序浏览
20可用积分
如题,我想在某个函数被调用时,打印那个时刻的函数调用栈到日志中;
就像GDB中bt命令显示的那样; 请教各位大牛这个是怎么实现的??

最佳答案

查看完整内容

编译:g++ stack.c -g -o stack -rdynamic

论坛徽章:
0
2 [报告]
发表于 2010-05-19 09:35 |只看该作者
本帖最后由 rain_fish 于 2010-05-19 10:18 编辑
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <execinfo.h>
  4. /* Obtain a backtrace and print it to stdout. */
  5. void
  6. print_trace (void)
  7. {
  8. void *array[10];
  9. size_t size;
  10. char **strings;
  11. size_t i;

  12. size = backtrace (array, 10);
  13. strings = backtrace_symbols (array, size);

  14. printf ("Obtained %zd stack frames.\n", size);

  15. for (i = 0; i < size; i++)
  16. printf ("%s\n", strings);

  17. free (strings);
  18. }

  19. int main()
  20. {
  21. print_trace ();
  22. }
复制代码
编译:g++ stack.c -g -o stack -rdynamic

论坛徽章:
0
3 [报告]
发表于 2010-05-19 10:33 |只看该作者
另外一个方法:
  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <execinfo.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. void backtrace()
  7. {
  8.         const int maxLevel = 200;
  9.         void* buffer[maxLevel];
  10.         int level = backtrace(buffer, maxLevel);
  11.         const int SIZE = 1024;
  12.         char cmd[SIZE] = "addr2line -C -f -e ";

  13.         // let prog point to the end of "cmd"
  14.         char* prog = cmd + strlen(cmd);

  15.         int r = readlink("/proc/self/exe", prog, sizeof(cmd) - (prog-cmd)-1);

  16.         FILE* fp = popen(cmd, "w");
  17.         if (!fp)
  18.         {
  19.                 perror("popen");
  20.                 return;
  21.         }
  22.         for (int i = 0; i < level; ++i)
  23.         {
  24.                 fprintf(fp, "%p\n", buffer[i]);
  25.         }

  26.         fclose(fp);
  27. }
  28. void foo(int, char*)
  29. {
  30.         backtrace();
  31. }
  32. void bar(double)
  33. {
  34.         foo(0, NULL);
  35. }

  36. int main()
  37. {
  38.         bar(0.0);
  39.         //A a;
  40.         return 0;
  41. }
复制代码

论坛徽章:
0
4 [报告]
发表于 2010-05-19 10:34 |只看该作者
当然,编译还是加上-rdynamic

g++ stack1.c -g -o stack1 -rdynamic

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
5 [报告]
发表于 2010-05-19 12:03 |只看该作者
本帖最后由 yjh777 于 2010-05-19 12:04 编辑
当然,编译还是加上-rdynamic

g++ stack1.c -g -o stack1 -rdynamic
rain_fish 发表于 2010-05-19 10:34



非常感谢; 可以打印调用栈,可是不能像gdb中bt那样打印每一级调用时的入参值:
Breakpoint 1, LOC_BacktraceHelper () at sys.c:11
11          nptrs = backtrace(apbuffer, 1024);
(gdb) bt
#0  LOC_BacktraceHelper () at sys.c:11
#1  0x08048770 in a (val=0) at sys.c:34
#2  0x0804878b in b (val=0) at sys.c:40
#3  0x080487b6 in main () at sys.c:48

(gdb) c
Continuing.
/a.out(LOC_BacktraceHelper+0x1f) [0x80486f3]
/a.out(a+0x12) [0x8048770]
/a.out(b+0x19) [0x804878b]
/a.out(main+0x29) [0x80487b6]
/lib/libc.so.6(__libc_start_main+0xdc) [0xb7e5087c]
/a.out [0x8048651]

Program exited normally.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
6 [报告]
发表于 2010-05-19 12:11 |只看该作者
armcc有没办法做到?

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
7 [报告]
发表于 2010-05-20 09:45 |只看该作者
armcc有没办法做到?
群雄逐鹿中原 发表于 2010-05-19 12:11



armcc是什么东西啊,编译器吗?

论坛徽章:
0
8 [报告]
发表于 2010-05-20 20:36 |只看该作者
回复 1# yjh777


    lz,你好,我的这个答案并没有参数的值啊,你有办法了?

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
9 [报告]
发表于 2010-05-21 10:15 |只看该作者
本帖最后由 yjh777 于 2010-05-21 10:19 编辑
回复  yjh777


    lz,你好,我的这个答案并没有参数的值啊,你有办法了?
rain_fish 发表于 2010-05-20 20:36


还没有,但是分数先送给你; 那个利用addr2line的方法很有创意 :)

本想看gdb代码发现有100多万行, 也没有什么文档,,

论坛徽章:
0
10 [报告]
发表于 2010-05-21 10:33 |只看该作者
回复 9# yjh777


    呵呵,我也对此问题很关注,咱们共同努力,如果有进展,互相交流,可否?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP