backtrace函数

 1、函数原型

#include <execinfo.h>    
int backtrace(void **buffer, int size);

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

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

  该函数将backtrace函数获取的信息转化为一个字符串数组,参数buffer是backtrace获取的堆栈指针,size是backtrace返回值。函数返回值是一个指向字符串数组的指针,它包含char*元素个数为size。每个字符串包含了一个相对于buffer中对应元素的可打印信息,包括函数名、函数偏移地址和实际返回地址。

  backtrace_symbols生成的字符串占用的内存是malloc出来的,但是是一次性malloc出来的,释放是只需要一次性释放返回的二级指针即可。

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

  该函数与backtrace_symbols函数功能相同,只是它不会malloc内存,而是将结果写入文件描述符为fd的文件中,每个函数对应一行。该函数可重入。

2、函数使用注意事项

  • backtrace的实现依赖于栈指针(fp寄存器),在gcc编译过程中任何非零的优化等级(-On参数)或加入了栈指针优化参数-fomit-frame-pointer后多将不能正确得到程序栈信息;
  • backtrace_symbols的实现需要符号名称的支持,在gcc编译过程中需要加入-rdynamic参数;
  • 内联函数没有栈帧,它在编译过程中被展开在调用的位置;
  • 尾调用优化(Tail-call Optimization)将复用当前函数栈,而不再生成新的函数栈,这将导致栈信息不能正确被获取。

3、捕获异常信号并打印堆栈

  当程序出现崩溃等异常时,会接收到内核发送给进程的异常信号,进程接收到异常信号后,可以在处理信号的时候将程序的堆栈信息打印出来,以便于程序调试。

4、程序示例:

#include <stdio.h>
#include <execinfo.h>
#include <unistd.h>
#include <stdlib.h>
#define BACKTRACE_SIZE 100

void print_backtrace()
{
    void* buffer[BACKTRACE_SIZE]={0};
    int pointer_num = backtrace(buffer, BACKTRACE_SIZE);
    char** string_buffer = backtrace_symbols(buffer, pointer_num);
    if(string_buffer == NULL)
    {
        printf("backtrace_symbols error");
        exit(-1);
    }
    
    printf("print backtrace begin\n");
    for(int i = 0; i < pointer_num; i++)
    {
        printf("%s\n", string_buffer[i]);
    }
    printf("print backtrace end\n");

    free(string_buffer);
    
    return;
}

void func(int num)
{
    if(num > 0)
    {
        func(--num);
    }
    else
    {
        print_backtrace();
    }
}

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        printf("input param error");
        return -1;
    }
    
    int input_num = atoi(argv[1]);
    func(input_num);

    return 0;
}

执行结果如下,注意在编译时带-rdynamic参数

 

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
回溯算法是一种通过穷举所有可能的解来求解问题的算法。它通常用于解组合优化问题,其中需要在给约束条件下找到最优解。01背包问题是一个经典的组合优化问题,它要求在给定背包容量和一组物品的重量和价值的情况下,选择一些物品放入背包中,使得背包中物品的总价值最大,同时不能超过背包的容量。 回溯算法解决01背包问题的基本思想是通过递归的方式遍历所有可能的解空间,并在搜索过程中进行剪枝,以提高搜索效率。具体步骤如下: 1. 定义一个递归函数backtrack,该函数接受当前背包容量、当前物品索引和当前背包中物品的总价值作为参数。 2. 在递归函数中,首先判断当前物品索引是否超过物品总数或者当前背包容量是否小于等于0,如果是,则返回当前背包中物品的总价值。 3. 如果不满足上述条件,则有两种情况: - 将当前物品放入背包中,更新背包容量和物品总价值,并递归调用backtrack函数。 - 不将当前物品放入背包中,直接递归调用backtrack函数。 4. 在递归调用后,比较两种情况的结果,返回较大的总价值作为当前背包中物品的最大总价值。 下面是一个使用回溯算法解决01背包问题的Python示例代码: ```python def backtrack(capacity, weights, values, index, total_value): if index >= len(weights) or capacity <= 0: return total_value # 将当前物品放入背包中 if capacity >= weights[index]: total_value1 = backtrack(capacity - weights[index], weights, values, index + 1, total_value + values[index]) else: total_value1 = 0 # 不将当前物品放入背包中 total_value2 = backtrack(capacity, weights, values, index + 1, total_value) return max(total_value1, total_value2) # 示例数据 capacity = 10 weights = [2, 3, 4, 5] values = [3, 4, 5, 6] max_value = backtrack(capacity, weights, values, 0, 0) print("Max value: ", max_value) ``` 这段代码中,我们定义了一个backtrack函数来求解01背包问题。在示例数据中,背包容量为10,物品的重量和价值分别为[2, 3, 4, 5]和[3, 4, 5, 6]。运行代码后,将输出最大总价值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咸鱼弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值