通过编程方式获取backtrace

本文介绍了如何利用glibc库中的backtrace函数和backtrace_symbols函数来获取程序的调用栈信息。通过示例代码展示了如何打印backtrace,并指出了为获得正确符号名需要使用-rdynamic编译选项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 http://www.top-e.org/jiaoshi/html/?164.html

在用GDB调试器时可以查看所谓的Backtrace,它包含一系列的函数调用信息,用命令backtracebt可以在GDB中查看函数调用栈的信息。有些场合没法使用GDB时,则可以用glibc库函数中的一些相关函数来得到backtrace的信息(在头文件execinfo.h中):

// 获取将backstrace信息,将地址存到buffer中。

// 参数size指定buffer的最大值,返回值则是backstrace的实际大小

int backtrace (void **buffer, int size)

 

// 根据buffer指定的地址,返回符号信息。参数size指定返回符号信息的大小

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

 

// 类似backtrace_symbols()函数,但是不需要malloc空间来存放符号信息,

// 而是将结果写到文件描述符fd所代表的文件中

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

使用函数backtrace_symbols()或者backtrace_symbols_fd()时,需要用-rdynamic编译才能得到正确的符号名,否则只能得到偏移地址。

下面的示例代码应用了backtrace()backtrace_symbols()函数来打印backtrace的信息:

     1  #include <execinfo.h>

     2  #include <stdio.h>

     3  #include <stdlib.h>

     4

     5  /* Obtain a backtrace and print it to stdout. */

     6  void print_trace (void)

     7  {

     8    void *array[10];

     9    size_t size;

    10    char **strings;

    11    size_t i;

    12

    13    size = backtrace (array, 10);

    14    strings = backtrace_symbols (array, size);

    15

    16    printf ("Obtained %zd stack frames./n", size);

    17

    18    for (i = 0; i < size; i++)

    19       printf ("%s/n", strings[i]);

    20

    21    free (strings);

    22  }

    23

    24  /* A dummy function to make the backtrace more interesting. */

    25  void dummy_function (void)

    26  {

    27    print_trace ();

    28  }

    29

    30  int main (void)

    31  {

    32    dummy_function ();

    33    return 0;

    34  }

编译运行的结果如下:

# gcc bt.c -rdynamic -o bt

# ./bt

Obtained 5 stack frames.

./bt(print_trace+0x14) [0x80486e4]

./bt(dummy_function+0xb) [0x8048765]

./bt(main+0x15) [0x 804877c ]

/lib/tls/libc.so.6(__libc_start_main+0xe4) [0x42015574]

./bt(backtrace_symbols+0x31) [0x8048641]

你可以应用这些函数在程序异常退出时打印backtrace或将它保存到某个文件中,用于之后的分析。更详细的介绍可以参考http://www.linuxjournal.com/article/6391

### 关于沈阳师范大学PTA Python编程题集 沈阳师范大学的PTA平台提供了丰富的Python编程练习题目,这些题目涵盖了基础语法、函数设计、数据结构以及算法等多个方面。以下是基于提供的引用内容和常见PTA题目的分析: #### 题目类型概述 1. **输入输出处理** 输入输出是Python程序的基础功能之一。例如,在引用[2]中展示了一个简单的格式化输出例子[^2]。通过`input()`获取用户输入并利用`format()`方法实现字符串插值打印。 2. **递归与回溯** 引用[1]提供了一种典型的递归解决方案[^1]。该代码片段实现了整数拆分问题的一个变体,其中定义了全局计数器来跟踪有效组合的数量,并采用深度优先搜索(DFS)策略枚举可能的结果集合。 3. **字符串操作** 字符串切片是一个重要的概念,但在某些情况下容易引起误解。比如引用[3]提到关于字符串索引范围的理解错误[^3]。实际上,当执行`print(st[0:-1])`时会省略最后一个字符而不是整个字符串的内容。 4. **数学计算** 圆周率π的应用广泛存在于几何学领域内的各种实际场景之中。对于圆形属性的相关运算通常涉及浮点数值精度控制等问题。 #### 示例代码解析 下面给出几个具体类型的经典习题及其解答思路: ##### 一、基本输入输出 ```python name = input("请输入姓名:") age = int(input("请输入年龄:")) weight = float(input("请输入体重(kg):")) output_str = f"我是{name},今年{age}岁,体重{round(weight*2,2)}斤" print(output_str) ``` ##### 二、递归求解子集划分 ```python def partition(n): result_list = [] def backtrack(path=[], remain=n, smallest=1): if not remain: result_list.append(list(path)) return for i in range(smallest,min(remain+1,n)): path.append(i) backtrack(path, remain-i,i ) path.pop() backtrack() return result_list partitions_of_5 =partition(5) for p in partitions_of_5 : print(' + '.join(map(str,p))) ``` ##### 三、字符串截取验证逻辑 ```python test_string='Hello World!' if test_string[:-1]== 'Hello World': print(True) else : print(False) ``` ##### 四、圆的参数计算 ```python import math radius=float(input("Enter radius of circle: ")) perimeter=2*math.pi*radius area=math.pi*(radius**2) formatted_perimeter="{:.2f}".format(perimeter) formatted_area="{:.2f}".format(area) print(f"The perimeter is {formatted_perimeter}") print(f"The area is {formatted_area}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值