linux 打印函数地址,linux下打印函数调用栈(stack backtrace in Linux)

今天遇到个这样的需求,希望能当动态链接库中抛出异常时,能把调用栈打印出来。经过在google上一翻搜寻,找到了一些线索。

我的文件目录如下:当前目录下是main.cpp 和test/

test下面是A.h, A.cpp(定义一个类)和backtrace.h, backtrace.cpp

第一步,实现打印调用栈,backtrace函数实现如下:

backtrace.cpp

#include "backtrace.h"

#include

#include

#include

#include

#include

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

#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

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命令可以在运行时打出函数调用栈信息,这种办法对静态链接有效,对动态库不行(暂时没发现行)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值