backtrace函数用法详解
backtrace函数简介
- 头文件包含
#include <execinfo.h>
- 函数定义
int backtrace(void
** buffer ,
int
char **backtrace_symbols(void *const
* buffer ,
int
void backtrace_symbols_fd(void *const
* buffer ,
int
int
backtrace函数常见使用错误
- 编译错误
warning: implicit declaration of function ‘backtrace’ [-Wimplicit-function-declaration]
解决办法:包含头文件
#include <execinfo.h>
backtrace函数详细描述
backtrace ()返回调用程序的回溯,在buffer 指向的数组中,回溯是程序当前活动的函数调用系列。buffer指向的数组中的每个项都是"void\ *" 类型,并且是对应堆栈帧的返回地址。size参数指定可以存储在buffer 中的最大地址数,如果回溯大于size ,则返回与size最近函数调用对应的地址;要获得完整的回溯,请确保buffer和size足够大。
给定buffer 中backtrace ()返回的地址集,backtrace_symbols ()将这些地址转换成一个字符串数组,以符号方式描述这些地址。size参数指定buffer 中的地址数。每个地址的符号表示由函数名(如果可以确定的话)、函数的十六进制偏移量和实际返回地址(十六进制)组成。字符串指针数组的地址作为backtrace_symbols ()的函数结果返回,该数组由backtrace_symbols ()返回malloc (3)ed,调用方必须释放该数组。(指针数组指向的字符串不需要也不应该被释放。)
backtrace_symbols_fd ()采用与backtrace_symbols ()相同的buffer和size参数,但它没有将字符串数组返回给调用者,而是将字符串(每行一个)写入文件描述符fd backtrace_symbols_fd ()不调用malloc (3),因此可以在后一个函数可能失败的情况下使用,但请参见注释。
backtrace函数返回值
backtrace ()返回buffer 中返回的地址数,该地址数不大于size ,如果返回值小于size ,则存储完整的回溯;如果它等于size ,那么它可能已经被截断,在这种情况下,不返回最早的堆栈帧的地址。
成功后,backtrace_symbols ()通过调用返回一个指向数组malloc (3)ed的指针;出错时,返回NULL。
backtrace函数其他说明
这些函数对函数的返回地址如何存储在堆栈上做了一些假设。请注意以下事项:
- 省略帧指针(正如任何gcc (1)'s非零优化级别所暗示的那样)可能会导致这些假设被违反。
- 内联函数没有堆栈框架。
- 尾调用优化导致一个堆栈帧替换另一个堆栈帧。
- backtrace ()和backtrace_symbols_fd ()不显式调用malloc (),但它们是libgcc 的一部分,在第一次使用时动态加载。动态加载通常触发对malloc (3)的调用,如果您需要对这两个函数的某些调用来不分配内存(例如,在信号处理程序中),则需要确保预先加载了libgcc。
如果不使用特殊链接器选项,符号名称可能不可用。对于使用GNU链接器的系统,有必要使用-rdynamic链接器选项。请注意,“静态”函数的名称不会公开,并且在回溯中不可用。
backtrace函数使用举例
下面的程序演示了backtrace ()和backtrace_symbols ()的使用,下面的shell会话显示了运行程序时我们可能会看到的内容:
" cc \-rdynamic prog.c \-o prog"
" ./prog 3"
backtrace() returned 8 addresses
\&./prog(myfunc3+0x5c) [0x80487f0]
\&./prog [0x8048871]
\&./prog(myfunc+0x21) [0x8048894]
\&./prog(myfunc+0x1a) [0x804888d]
\&./prog(myfunc+0x1a) [0x804888d]
\&./prog(main+0x65) [0x80488fb]
\&/lib/libc.so.6(__libc_start_main+0xdc) [0xb7e38f9c]
\&./prog [0x8048711]
Program source&
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BT_BUF_SIZE 100
void
myfunc3(void)
{
int nptrs;
void *buffer[BT_BUF_SIZE];
char **strings;
nptrs = backtrace(buffer, BT_BUF_SIZE);
printf("backtrace() returned %d addresses\en", 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 (int j = 0; j < nptrs; j++)
printf("%s\en", strings[j]);
free(strings);
}
static void /* "static" means don\(aqt 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\en", argv[0]);
exit(EXIT_FAILURE);
}
myfunc(atoi(argv[1]));
exit(EXIT_SUCCESS);
}
评论区