linux环境在程序中打印调用栈的方法
2014-06-27 14:44
295 查看
使用调试工具进行bug处理时非常有用,在阅读和分析源代码时也非常有用,以下代码就说明了如何在自己的程序中打印调用堆栈;
#include <stdio.h>
#include <execinfo.h>
#include <stdlib.h>
#include <unistd.h>
void print_trace(void);
void mytrace(void)
{
int j, nptrs;
#define SIZE 100
void *buffer[100];
char **strings;
nptrs = backtrace(buffer, SIZE);
printf("backtrace() returned %d addresses\n", nptrs);
/* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
* would produce similar output to the following: */
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
for (j = 0; j < nptrs; j++)
printf("%s\n", strings[j]);
free(strings);
}
void funcC()
{
/* 打印调用堆栈,看看谁调用了本函数 */
print_trace();
//mytrace();
}
void funcB()
{
funcC();
}
void funcA()
{
funcB();
}
int main (void)
{
funcA();
return 0;
}
void print_trace(void)
{
int i;
const int MAX_CALLSTACK_DEPTH = 32; /* 需要打印堆栈的最大深度 */
void *traceback[MAX_CALLSTACK_DEPTH]; /* 用来存储调用堆栈中的地址 */
/* 利用 addr2line 命令可以打印出一个函数地址所在的源代码位置
* 调用格式为: addr2line -f -e /tmp/a.out 0x400618
* 使用前,源代码编译时要加上 -rdynamic -g 选项
*/
char cmd[512] = "addr2line -f -e ";
char *prog = cmd + strlen(cmd);
/* 得到当前可执行程序的路径和文件名 */
int r = readlink("/proc/self/exe",prog,sizeof(cmd)-(prog-cmd)-1);
/* popen会fork出一个子进程来调用/bin/sh, 并执行cmd字符串中的命令,
* 同时,会创建一个管道,由于参数是'w', 管道将与标准输入相连接,
* 并返回一个FILE的指针fp指向所创建的管道,以后只要用fp往管理里写任何内容,
* 内容都会被送往到标准输入,
* 在下面的代码中,会将调用堆栈中的函数地址写入管道中,
* addr2line程序会从标准输入中得到该函数地址,然后根据地址打印出源代码位置和函数名。
*/
FILE *fp = popen(cmd, "w");
/* 得到当前调用堆栈中的所有函数地址,放到traceback数组中 */
int depth = backtrace(traceback, MAX_CALLSTACK_DEPTH);
for (i = 0; i < depth; i++)
{
/* 得到调用堆栈中的函数的地址,然后将地址发送给 addr2line */
fprintf(fp, "%p\n", traceback[i]);
/* addr2line 命令在收到地址后,会将函数地址所在的源代码位置打印到标准输出 */
}
fclose(fp);
}
<以上代码来自网络>
#include <stdio.h>
#include <execinfo.h>
#include <stdlib.h>
#include <unistd.h>
void print_trace(void);
void mytrace(void)
{
int j, nptrs;
#define SIZE 100
void *buffer[100];
char **strings;
nptrs = backtrace(buffer, SIZE);
printf("backtrace() returned %d addresses\n", nptrs);
/* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
* would produce similar output to the following: */
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
for (j = 0; j < nptrs; j++)
printf("%s\n", strings[j]);
free(strings);
}
void funcC()
{
/* 打印调用堆栈,看看谁调用了本函数 */
print_trace();
//mytrace();
}
void funcB()
{
funcC();
}
void funcA()
{
funcB();
}
int main (void)
{
funcA();
return 0;
}
void print_trace(void)
{
int i;
const int MAX_CALLSTACK_DEPTH = 32; /* 需要打印堆栈的最大深度 */
void *traceback[MAX_CALLSTACK_DEPTH]; /* 用来存储调用堆栈中的地址 */
/* 利用 addr2line 命令可以打印出一个函数地址所在的源代码位置
* 调用格式为: addr2line -f -e /tmp/a.out 0x400618
* 使用前,源代码编译时要加上 -rdynamic -g 选项
*/
char cmd[512] = "addr2line -f -e ";
char *prog = cmd + strlen(cmd);
/* 得到当前可执行程序的路径和文件名 */
int r = readlink("/proc/self/exe",prog,sizeof(cmd)-(prog-cmd)-1);
/* popen会fork出一个子进程来调用/bin/sh, 并执行cmd字符串中的命令,
* 同时,会创建一个管道,由于参数是'w', 管道将与标准输入相连接,
* 并返回一个FILE的指针fp指向所创建的管道,以后只要用fp往管理里写任何内容,
* 内容都会被送往到标准输入,
* 在下面的代码中,会将调用堆栈中的函数地址写入管道中,
* addr2line程序会从标准输入中得到该函数地址,然后根据地址打印出源代码位置和函数名。
*/
FILE *fp = popen(cmd, "w");
/* 得到当前调用堆栈中的所有函数地址,放到traceback数组中 */
int depth = backtrace(traceback, MAX_CALLSTACK_DEPTH);
for (i = 0; i < depth; i++)
{
/* 得到调用堆栈中的函数的地址,然后将地址发送给 addr2line */
fprintf(fp, "%p\n", traceback[i]);
/* addr2line 命令在收到地址后,会将函数地址所在的源代码位置打印到标准输出 */
}
fclose(fp);
}
<以上代码来自网络>
相关文章推荐
- linux用户态程序定位方法总结1 打印调用栈
- Linux下使用函数打印程序堆栈错误的方法
- linux环境中的arm程序编辑器eclipse安装及使用方法
- 在linux环境下编译运行OpenCV程序的两种方法
- [转]在linux环境下编译运行OpenCV程序的两种方法
- 在linux环境下编译运行OpenCV程序的两种方法
- Linux环境定位C程序内存泄露以及非法访问的方法
- 关于在linux环境中用eclipse搭建c++程序开发平台的方法
- 在linux环境下编译运行OpenCV程序的两种方法
- Linux 程序开发打印 Debug 信息的使用技巧--C语言中几种输出调试信息的方法
- Linux 程序开发打印 Debug 信息的使用技巧--C语言中几种输出调试信息的方法
- 在linux环境下编译运行OpenCV程序的两种方法
- 在linux环境下编译运行OpenCV程序的两种方法
- 【程序中打印调用栈信息方法】 backtrace和backtrace_symbols函数
- linux环境arm裸机程序学习笔记1----makefile,中断,下载程序方法
- Linux环境下后台一直运行程序不退出的方法
- 在linux环境下编译运行OpenCV程序的两种方法 - woshijpfgg
- Linux环境通过java虚拟机定位程序问题位置的方法
- linux环境下GDB与core dump调试程序方法
- 在linux环境下编译运行OpenCV程序的两种方法