事情的原由是这样的,以前同事的代码有一个内存池出现了没有回收的状况。也就是是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) 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 }
编译:spa
g++ -Wall -g backtrace.cpp -o bt
执行:调试
./bt
效果:日志
1 Obtained 5 stack frames. 2 0x4009e6 _Z11print_tracev /home/dyf/Project/Tool/backtrace.cpp:59 3 0x400b71 _Z14dummp_functionv /home/dyf/Project/Tool/backtrace.cpp:83 4 0x400b87 main /home/dyf/Project/Tool/backtrace.cpp:88 5 0x7fa51f761af5 __libc_start_main ??:0 6 0x400769 _start ??:0
大体知足本身的需求效果,函数名称还须要修饰一下!code