打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Linux下追踪函数调用,打印栈帧

      事情的起因是这样的,之前同事的代码有一个内存池出现了没有回收的情况。也就是是Pop出来的对象没有Push回去,情况很难复现,所以在Pop里的打印日志,跟踪是谁调用了它,我想在GDB调试里可以追踪调用的栈帧,那也一定有方法实现。首先上网搜索了一下,并没有结果!还好代码量不是很多,只能用最笨的方法,在每个调用Pop的地方,传参,把调用的文件,行号作为字符串传进去,在日志里打印!忙活完了,总感觉一定是有方法可以实现查看调用栈帧的,于是在QQ群里的问了下,果然有这方面经验的同学给出了答案!

    主要是通过backtrace返回调用的栈帧,然后通过backtrace_symbols把地址转换为字符串。最后,在Linux下有个工具addr2line可以将地址转换为文件名和行号!通过管道调用addr2line,最后打印调用栈帧。

 1 #include <execinfo.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 /* 6  * 打印栈帧 7  *  8  * 通过backtrace,backtrace_symbols获取栈帧信息,然后建立管道,通过addr2line解析 9  * 10  */11 12 int32_t myexec(const char *cmd) 13 {14     FILE *pp = popen(cmd, "r"); //建立管道15     if (!pp) 16     {17         return -1;18     }
19 char tmp[1024];
while (fgets(tmp, sizeof(tmp), pp) != NULL) 22 {23 if (tmp[strlen(tmp) - 1] == '\n') 24 {25 tmp[strlen(tmp) - 1] = '\0'; //去除换行符26 }27 28 printf("%-30s",tmp);29 }30 printf("\n");31 pclose(pp); //关闭管道32 return 0;33 }34 35 void parseName(char * str,char *exeName,char *addr)36 {37 char *strTemp = str;38 char * addrTemp;39 while (*strTemp != NULL)40 {41 if (*strTemp == '(')42 memcpy(exeName, str, strTemp - str);43 44 if (*strTemp == '[')45 addrTemp = strTemp;46 47 if (*strTemp == ']')48 memcpy(addr, str + (addrTemp - str) + 1, strTemp - addrTemp - 1);49 strTemp++;50 }51 }52 53 void print_trace(void)54 {55 void *array[10];56 size_t size;57 char **strings;58 59 size = backtrace(array,10);60 strings = backtrace_symbols(array,size);61 62 printf("Obtained %zd stack frames.\n",size);63 char cmd[500] = {0}; 64 char exeName[100] = {0};65 char addr[100] = {0};66 for(size_t i = 0;i < size;i++)67 {68 memset(cmd,0,sizeof(cmd));69 memset(exeName,0,sizeof(exeName));70 memset(addr,0,sizeof(addr));71 72 parseName(strings[i],exeName,addr);73 printf("%-15s",addr);74 sprintf(cmd,"addr2line -f -e %s %s",exeName,addr);75 myexec(cmd);76 } 78 }79 80 void dummp_function(void)81 {82 print_trace();83 }84 85 int main(int argc,char *argv[])86 {87 dummp_function();88 return 0;89 }

编译:

gcc -Wall -g backtrace.cpp -o bt

执行:

./bt

效果:

1 Obtained 5 stack frames.2 0x4009e6       _Z11print_tracev              /home/dyf/Project/Tool/backtrace.cpp:593 0x400b71       _Z14dummp_functionv           /home/dyf/Project/Tool/backtrace.cpp:834 0x400b87       main                          /home/dyf/Project/Tool/backtrace.cpp:885 0x7fa51f761af5 ??                            ??:0                          6 0x400769       _start                        ??:? 

大致满足自己的需求效果,函数名称还需要修饰一下!

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
strchr函数
(6)Android Native/Tombstone Crash Log 详细分析[原创]
实现整数转化为字符串函数itoa()函数
可以通过函数strncat strcat实现从字符加入到字符串中
ASP技巧集锦1
Excel 汉字转拼音
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服