侧边栏壁纸
博主头像
noerror

虚灵不寐,众理具而万事出。

  • 累计撰写 239 篇文章
  • 累计创建 9 个标签
  • 累计收到 2 条评论
标签搜索

目 录CONTENT

文章目录

backtrace函数用法详解

noerror
2022-10-04 / 0 评论 / 0 点赞 / 233 阅读 / 1,155 字 / 正在检测是否收录...

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);
}
0

评论区