本帖最后由 kylin_try 于 2017-2-6 08:41 编辑

在头文件"execinfo.h"中声明了三个函数用于获取当前线程的函数调用堆栈。

#include

int backtrace(void **buffer, intsize);

char **backtrace_symbols(void *const *buffer, intsize);

void backtrace_symbols_fd(void *const *buffer, intsize, intfd);

man 帮助:

DESCRIPTION         backtrace() returns a backtrace for the calling program, in the array pointed to by buffer.  A backtrace is the series of currently active function calls for the program.  Each item in the array pointed to by buffer is of type void *, and is the return address from the corresponding stack frame.  The size argument specifies the maximum number of addresses that can be stored in buffer.  If the backtrace is larger than size, then the addresses corresponding to the size most recent function calls are returned; to obtain the complete backtrace, make sure that buffer and size are large enough.Given the set of addresses returned by backtrace() in buffer, backtrace_symbols() translates the addresses into an array of strings that describe the addresses symbolically. The size argument specifies the number of addresses in buffer.  The symbolic representation of each address consists of the function name (if this can be determined), a hexadecimal offset into the function, and the actual return address (in hexadecimal). The address of the array of string pointers is returned as the function result of backtrace_symbols().  This array ismalloc(3)ed by backtrace_symbols(), and must be freed by the caller.  (The strings pointed to by the array of pointers need not and should not be freed.)backtrace_symbols_fd() takes the same buffer and size arguments as backtrace_symbols(), but instead of returning an array of strings to the caller,it writes the strings, one per line, to the file descriptor fd.  backtrace_symbols_fd() does not call malloc(3), and so can be employed in situations where the latter function might fail.

int backtrace(void **buffer,int size)

该函数用与获取当前线程的调用堆栈,获取的信息将会被存放在buffer中,它是一个指针数组。参数 size 用来指定buffer中可以保存多少个void* 元素。函数返回值是实际获取的指针个数,最大不超过size大小在buffer中的指针实际是从堆栈中获取的返回地址,每一个堆栈框架有一个返回地址。

注意某些编译器的优化选项对获取正确的调用堆栈有干扰,另外内联函数没有堆栈框架;删除框架指针也会使无法正确解析堆栈内容

char ** backtrace_symbols (void *const *buffer, int size)

backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组. 参数buffer应该是从backtrace函数获取的数组指针,size是该数组中的元素个数(backtrace的返回值),函数返回值是一个指向字符串数组的指针,它的大小同buffer相同.每个字符串包含了一个相对于buffer中对应元素的可打印信息.它包括函数名,函数的偏移地址,和实际的返回地址

现在,只有使用ELF二进制格式的程序和苦衷才能获取函数名称和偏移地址.在其他系统,只有16进制的返回地址能被获取.另外,你可能需要传递相应的标志给链接器,以能支持函数名功能(比如,在使用GNU ld的系统中,你需要传递(-rdynamic))

backtrace_symbols生成的字符串都是malloc出来的,但是不要最后一个一个的free,因为backtrace_symbols是根据backtrace给出的call stack层数,一次性的malloc出来一块内存来存放结果字符串的,所以,像上面代码一样,只需要在最后,free backtrace_symbols的返回指针就OK了。这一点backtrace的manual中也是特别提到的。

注意:如果不能为字符串获取足够的空间函数的返回值将会为NULL

void backtrace_symbols_fd (void *const *buffer, int size, int fd)

backtrace_symbols_fd与backtrace_symbols 函数具有相同的功能,不同的是它不会给调用者返回字符串数组,而是将结果写入文件描述符为fd的文件中,每个函数对应一行.它不需要调用malloc函数,因此适用于有可能调用该函数会失败的情况。man手册中示例:#include

#include

#include

#include

void

myfunc3(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);

}

static void   /* "static" means don't export the symbol... */

myfunc2(void)

{

myfunc3();

}

void

myfunc(int ncalls)

{

if (ncalls > 1)

myfunc(ncalls - 1);

else

myfunc2();

}

int

main(int argc, char *argv[])

{

if (argc != 2) {

fprintf(stderr, "%s num-calls\n", argv[0]);

exit(EXIT_FAILURE);

}

myfunc(atoi(argv[1]));

exit(EXIT_SUCCESS);

}

结果:

总结:使用以下几个函数既可完成堆栈信息的打印

int backtrace (void **buffer, int size)

char ** backtrace_symbols (void *const *buffer, int size)

char* abi::__cxa_demangle

(

const char * mangled_name,

char * output_buffer,

size_t * length,

int * status

)

1. backtrace可以在程序运行的任何地方被调用,返回各个调用函数的返回地址,可以限制最大调用栈返回层数。

2. 在backtrace拿到函数返回地址之后,backtrace_symbols可以将其转换为编译符号,这些符号是编译期间就确定的

3. 根据backtrace_symbols返回的编译符号,abi::__cxa_demangle可以找到具体地函数方法

转:http://www.cnblogs.com/mickole/p/3246702.html

php 打印函数调用栈,利用backtrace和backtrace_symbols函数打印调用栈信息相关推荐

  1. 【译】理解Javascript函数执行—调用栈、事件循环、任务等

    原文作者:Gaurav Pandvia 原文链接:medium.com/@gaurav.pan- 文中部分链接可能需要梯子. 欢迎批评指正. 现如今,web开发者(我们更喜欢被叫做前端工程师)用一门脚 ...

  2. 「译」理解Javascript函数执行—调用栈、事件循环、任务等

    现如今,web开发者(我们更喜欢被叫做前端工程师)用一门脚本语言就能做任何事情,从提供浏览器中的交互,到开发电脑游戏.桌面工具.跨平台移动应用,甚至可以在服务端部署(如最流行的Node.js)来连结任 ...

  3. [译]深入理解JavaScript函数执行—调用栈,事件循环和任务等

    Web 开发者,或者前端工程师(我们更喜欢别人这么称呼)现如今几乎能做所有的工作,从扮演一个浏览器内部交互性的角色,到制作电脑游戏.桌面控件.跨平台手机应用,甚至还可以把它写在服务器端(最流行的是no ...

  4. 关于ceph源码 backtrace 打印函数调用栈

    当集中精力看一个问题的时候,时间久了就会有这样一个状态,天空飘来五个字,那都不算事 ceph源码庞大的体量以及复杂的设计让很多人望而却步,尤其是大量的纯虚函数更是让读者迷失在代码的海洋,这个时候函数调 ...

  5. java打印堆栈信息linux,在C/C++程序里打印调用栈信息(转载)

    原文出处  http://blog.csdn.net/yetyongjin/article/details/7759144 以下不能windows + mingw下执行.  windows下参考 ht ...

  6. 在WinDBG中查看调用栈的命令

    命令 ========== k k命令显示的是一定数量的栈帧, 其中帧的数量是由.kframes命令来控制的, 默认值是256. kp 5 显示调用栈中前5个函数以及他们的参数. kb 5 显示调用栈 ...

  7. g++ linux 编译开栈_使用g++编译器扩大程序可用栈空间

    如题,在写一些程序的时候我们有时会开一个比较大的数组或进行层数较多的dfs.这时候,程序常常会报错,于是就很无奈. 其实,虽然Windows给程序的默认栈空间比较小,我们还是有办法去扩大这个程序运行栈 ...

  8. 写一个 JS 调用栈可视化工具 hound-trace

    背景 最近在分析一些框架源码,在写笔记的时候,一些函数的调用栈希望用流程图的形式记录下来,打开 http://draw.io[1] 就是一顿操作,画了几个调用栈之后,感觉很麻烦.于是蹲在厕所里的我开始 ...

  9. c语言栈的实现以及操作_数据结构之链栈基本操作的实现详解(C语言描述)

    迎新过后,来带领你好好学习的小软准时归来,快带着上次学习链表操作的记忆和我开启新的旅程吧: 链栈:就是栈的链式存储结构,简称链栈. 首先我们要考虑的就是链栈的存储结构,由于栈只是在栈顶进行插入和删除操 ...

最新文章

  1. 高斯白噪声的Verilog实现
  2. ASP.NET 例程完全代码版(5)——通过web.config配置数据库连接池
  3. 利用numpy生成各种波
  4. Java并发修改异常的源码解析
  5. 关于spring cloud的几个问题
  6. 人的手臂的自由度的数目以及六自由度机械臂的限制
  7. [Java] 蓝桥杯ADV-210 算法提高 2-1屏幕打印
  8. SQL Server触发器创建、删除、修改、查看
  9. C语言自学之路八(数组(重点)详解)
  10. 对java老师的评价及建议_对老师的评价和建议
  11. Java @link 注释
  12. 《龙腾世纪2》图文流程攻略
  13. 基于Qt的局域网即时通讯软件
  14. steam游戏存档迁移
  15. C/C++ 判断当前操作系统语言、获取当前操作系统使用语言 GetSystemDefaultLangID
  16. 在Matlab图片里输入数学公式、符号和希腊字母的方法
  17. 微信红包开发设计思路
  18. cad字体安装_如何安装CAD字体库,让打开图纸时显示?的现象都消失?【AutoCAD教程】...
  19. 12本互联网科技大佬推荐的必读书籍
  20. Linux的历史----Linux内核剖析(一)

热门文章

  1. 分享我对领域驱动设计(DDD)的学习成果
  2. 规模估算失准 软件开发成空中楼阁
  3. 在IDEA中`New`没有`Mapper`文件选项(亲测)
  4. redis没有加密码导致服务器被当做矿机了
  5. php5和php7的bccomp计算精度区别
  6. 这些密码千万不要用!黑客5分钟即可破解!
  7. tomcat java 参数乱码_javaweb乱码(tomcat服务器)
  8. python中输入的字怎么表示_简单讲解Python中的字符串与字符串的输入输出
  9. 计算机心得300,计算机实训总结计算机实训心得300
  10. java创建具体时间点_java单例饿汉模式对象创建时间点疑问