linux下打印函数调用栈(stack backtrace in Linux)
来源:互联网 发布:javascript 文字滚动 编辑:程序博客网 时间:2024/05/22 17:41
今天遇到个这样的需求,希望能当动态链接库中抛出异常时,能把调用栈打印出来。经过在google上一翻搜寻,找到了一些线索。
我的文件目录如下:当前目录下是main.cpp 和test/
test下面是A.h, A.cpp(定义一个类)和backtrace.h, backtrace.cpp
第一步,实现打印调用栈,backtrace函数实现如下:
backtrace.cpp
#include "backtrace.h"
#include <unistd.h>
#include <stdio.h>
#include <execinfo.h>
#include <stdlib.h>
#include <string.h>
void backtrace()
{
const int maxLevel = 200;
void* buffer[maxLevel];
int level = backtrace(buffer, maxLevel);
const int SIZE = 1024;
char cmd[SIZE] = "addr2line -C -f -e ";
// let prog point to the end of "cmd"
char* prog = cmd + strlen(cmd);
int r = readlink("/proc/self/exe", prog, sizeof(cmd) - (prog-cmd)-1);
FILE* fp = popen(cmd, "w");
if (!fp)
{
perror("popen");
return;
}
for (int i = 0; i < level; ++i)
{
fprintf(fp, "%p\n", buffer[i]);
}
fclose(fp);
}
main.cpp
include <stdio.h>
#include "A.h"
#include "backtrace.h"
void foo(int, char*)
{
backtrace();
}
void bar(double)
{
foo(0, NULL);
}
int main()
{
bar(0.0);
//A a;
return 0;
}
按如下编译,注意-g 和 -rdynamic参数。
[Charlie@localhost so]$ g++ -g -rdynamic -Itest main.cpp test/backtrace.cpp
[Charlie@localhost so]$ ./a.out
backtrace()
/home/Charlie/workspace/so/test/backtrace.cpp:12
foo(int, char*)
/home/Charlie/workspace/so/main.cpp:7
bar(double)
/home/Charlie/workspace/so/main.cpp:11
main
/home/Charlie/workspace/so/main.cpp:17
??
??:0
_start
??:0
从上述输出结果可以看到,调用栈被正确地打印了出来,包括函数名,代码文件:行数
下面的??表示无法得到代码文件名,必要时可能进行过滤。
第二步,尝试在动态链接库中打印调用栈。
A.cpp
#include "A.h"
#include "backtrace.h"
#include <stdio.h>
A::A()
{
printf("A::A\n");
backtrace();
}
main.cpp中相关改动为:
int main()
{
//bar(0.0);
A a;
return 0;
}
首先编译生成动态链接库:
[Charlie@localhost test]$ g++ -g -rdynamic -o libA.so -shared A.cpp backtrace.cpp
[Charlie@localhost so]$ g++ -g -rdynamic -Ltest -Itest -lA main.cpp
[Charlie@localhost so]$ ./a.out
A::A
??
??:0
??
??:0
main
/home/Charlie/workspace/so/main.cpp:7
??
??:0
_start
??:0
结果非常遗憾,只有main函数能打出文件名和行数。动态链接库中不能打出来。
动态库不行,试试静态库呢?凭直觉应该是行的,因为它和直接编译链接差不多嘛。
cd 到test下面,
[Charlie@localhost test]$ g++ -g -rdynamic -c backtrace.cpp A.cpp
编译生成.o文件,再用ar将其打成.a文件。
[Charlie@localhost test]$ ar -rc libA.a A.o backtrace.o
[Charlie@localhost test]$ cd ..
[Charlie@localhost so]$ g++ -g -rdynamic -Itest main.cpp test/libA.a
[Charlie@localhost so]$ ./a.out
A::A
backtrace()
/home/Charlie/workspace/so/test/backtrace.cpp:12
A
/home/Charlie/workspace/so/test/A.cpp:9
main
/home/Charlie/workspace/so/main.cpp:17
??
??:0
_start
??:0
这次执行果然得到了我们希望的结果,正确地打印出了栈信息。
结论:利用backtrace借助addr2line命令可以在运行时打出函数调用栈信息,这种办法对静态链接有效,对动态库不行(暂时没发现行)。
转自:http://hi.baidu.com/anatacollin/item/d31d031135202d9d99ce33b9
- linux下打印函数调用栈(stack backtrace in Linux)
- linux下打印函数调用栈(stack backtrace in Linux)
- linux打印当前函数调用栈backtrace
- linux用户程序调用栈打印backtrace
- linux下追踪函数调用堆栈backtrace
- Linux下利用backtrace追踪函数调用堆栈
- 利用backtrace函数打印函数调用栈
- 使用backtrace打印函数调用栈
- 高效获得Linux函数调用栈/backtrace的方法
- 高效获得Linux函数调用栈/backtrace的方法
- 高效获得Linux函数调用栈/backtrace的方法
- linux中追踪函数backtrace调用堆栈
- 打印函数调用栈----backtrace原理简单实现
- 使用Backtrace函数打印调用栈 - Debug居家必备
- 利用backtrace和backtrace_symbols函数打印调用栈信息
- 使用Backtrace函数打印调用栈 - Debug居家必备
- 利用backtrace和backtrace_symbols函数打印调用栈信息
- 利用backtrace和backtrace_symbols函数打印调用栈信息
- android httpUrlConnection 方式从网络上面下载图片
- Vim Commands Cheat Sheet
- [转载]基于ssl加密通信的rmi应用实现
- maven编译报错Cannot locate the chosen ObjectFactory implementation: spring - [unknown locatio
- SqlServer中检查对象是否已经存在
- linux下打印函数调用栈(stack backtrace in Linux)
- android httpurlconnection 方式上传图片
- php网站调试
- php项目开发问题汇总
- 简单的编程 if while for,留着自己备用
- maven编译报错 http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml
- 打造圆润的mfc
- 数据库中使用的数据结构:B 树、B+ 树
- 解决Eclipse中文乱码