linux内核打印应用堆栈,linux下在应用层打印调用堆栈

如下函数可以在任意函数中打印出当前的调用堆栈

输出到标准输出设备,一般就是命令行了

需要注意的是必须包含下面的标准库头文件,因为man backtrace,它的声明就在这个头文件中

#include

下面简单介绍一下工作原理

主要基本2个调用来实现的:

首先是命令行的addr2line。他可以把一个可执行文件中的函数地址转换为源代码的位置以及当前函数名

要实现这个还有个前提,必须编译调试版本,应此在Makefile里面CFLAGS必须有-rdynamic -g 编译选项

其次,调用backtrace 获得当前函数的指针

最后通过popen打开一个标准输出的文件句柄,把addr2line 带上正确的参数发送过去,标准输出会等待继续函数地址,就会连续的打印函数地址对应的源代码信息

在backtrace获得一个函数地址数组以后,循环执行fprintf向标准输出写入这些函数地址,注意,每个指针后面要跟上\r\n作为结束符才能正确执行,否则看不到正确的输出

下面是完整的代码:

void print_trace(void) {

int i;

int MAX_CALLSTACK_DEPTH = 32;

void *traceback[MAX_CALLSTACK_DEPTH];

char cmd[512] = "addr2line -f -e ";

char *prog = cmd + strlen(cmd);

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

/*printf("%s\n",cmd);*/

FILE *fp = popen(cmd, "w");

int depth = backtrace(traceback, MAX_CALLSTACK_DEPTH);

for (i = 0; i < depth; i++)

{

/*printf("%p\n",traceback[i]);*/

fprintf(fp, "%p\n\r", traceback[i]);

}

fclose(fp);

}

如果是后台程序,输出没有定向到终端,那么可以用backtrace_symbols函数,把调用栈信息写到文件里面,上面的函数可以这样改一下

void print_trace(char *filename)

{

int i = 0;

int len = strlen(filename) + 1;

char *name_t = (char *)malloc(len + 1);

memset(name_t,0,len);

strcpy(name_t,filename);

const int MAX_CALLSTACK_DEPTH = 32;

void *traceback[MAX_CALLSTACK_DEPTH];

char **stackinfo_string;

printf("%s\n",name_t);

char *temp = strrchr(name_t,'/');

temp ++;

for (;*temp != 0;temp++){

putchar(*temp);

*temp = 0;

}

strcat(name_t,"trace_info.log");

printf("%s\n",name_t);

int fd = open((const char *)name_t,O_CREAT|O_WRONLY|O_APPEND,0);

int depth = backtrace(traceback, MAX_CALLSTACK_DEPTH);

stackinfo_string = backtrace_symbols(traceback,depth);

for(i =0 ; i < depth ;i++) {

write(fd,stackinfo_string[i],strlen(stackinfo_string[i]));

write(fd,"\r\n",2);

}

close(fd);

free(stackinfo_string);

}

backtrace_symbols的不足之处是无法解析静态函数的符号信息,这点在使用中需要考虑清楚

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值