Linux用backtrace定位分析段错误

Linux c/c++开发环境下,可以使用以下函数来获取进程调用的堆栈信息

#include <execinfo.h>

int backtrace(void **buffer, int size);

该函数用于获取当前线程的调用堆栈,获取的信息将会被存放在buffer中,它是一个指针列表。
参数 size 用来指定buffer中可以保存多少个void* 元素。
函数返回值是实际获取的指针个数,最大不超过size大小,为了取得全部的函数调用列表,
应保证buffer和size足够大。


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

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


简单的

#include <iostream> 
#include <execinfo.h>
#include <signal.h>

using namespace std;  

 
 void test_sig(int sig)
 {
    void *array[10];
    int size, i;
    char **strings;

    fprintf(stderr, "\nSegmentation fault\n");
    size = backtrace(array, 10);
    fprintf(stderr, "\nBacktrace (%d deep):\n", size);

    strings = backtrace_symbols(array, size);
    for (i=0; i < size; i++)
    {
        fprintf(stderr, "%d: %s, signal is %d\n", i, strings[i], sig);
    }

    free(strings);
    strings = NULL;
 }

int main() 
{ 
    signal(SIGSEGV, test_sig);
    int *p = nullptr;
    *p = 1;
}  

输出结果

Segmentation fault

Backtrace (5 deep):
0: ./a() [0x4011e0], signal is 11
1: /lib/x86_64-linux-gnu/libc.so.6(+0x430c0) [0x7ff39e8f80c0], signal is 11
2: ./a() [0x40129c], signal is 11
3: /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7ff39e8d90b3], signal is 11
4: ./a() [0x4010ee], signal is 11

通过addr2line 可以定位的有段错误的地方
xxx@xxx:~/test$ addr2line -e a 0x40129c
/home/dwb/test/a.cpp:58

动态库

动态库找到的地址不是函数实际的地址,需要将堆栈异常的地址减去库文件加载的开始地址。可通过查询 /proc下的maps来确定库文件的开始地址。

可在main函数中加入

char maps[128] = {0x00};
snprintf(maps, sizeof(maps), "cat /proc/%d/maps", getpid());
system(maps);

结果会在终端输出。

如果是将异常导入到txt文件中的话,需要按照如下操作

 

 

 结果

 计算两个地址的差值,然后用addr2line来输出异常的地方如下:

int system(const char *command)
system()函数调用/bin/sh来执行参数指定的命令,/bin/sh 一般是一个软连接,指向某个具体的shell

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值