欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

linux下使用backtrace函数捕定位段错误问题

程序员文章站 2022-07-14 23:48:35
...

Linux下C语言下编程时不时会错遇到段错误问题,段错误常常由于指针访问了非法的内存地址所造成的,但是系统并没有给我们指出访问哪个地方的内存地址出错。下面我们使用信号捕捉的方法,利用backtrace函数得到段错误的信息,从而定位段错误所处的位置。

这里使用到两个函数:backtrace和backtrace_symbols;

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

获取堆栈函数调用列表

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

获取的地址转为描述这些地址的字符串数组。


1. 编写segfault.c程序,使用signal信号函数捕捉SIGSEGV信号,然后用backtrace函数获取列表。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <execinfo.h>

void test1(int number) {
	char *p= (char *)number;
	*p = 's';
	printf("%s: test1\n", __FUNCTION__);
}


void DebugBacktrace(void) {
	#define SIZE 100
	void *array[SIZE];
	int size, i;
	char **strings;

    fprintf(stderr, "\n Segmentation fault \n");
    size = backtrace(array, SIZE);
    fprintf(stderr, "Backtrace (%d deef):\n", size);

    strings =backtrace_symbols(array, size);

    for(i =0; i < size; i++)
    	fprintf(stderr, "%d: %s\n", i, strings[i]);

 	free(strings);
 	exit(-1);
}

int main(void) {
	char data = 1;

	signal(SIGSEGV, DebugBacktrace);
	test1(data);
}

2. 编译运行

gcc -o seg segfault.c 
./seg

得到段错误信息

Segmentation fault 
Backtrace (6 deef):
0: ./seg() [0x4007eb]
1: /lib/x86_64-linux-gnu/libc.so.6(+0x36cb0) [0x7fde9eb9bcb0]
2: ./seg() [0x400795]
3: ./seg() [0x4008ca]
4: /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7fde9eb86f45]
5: ./seg() [0x4006b9]

3. 使用objdump定位段错误的地址

objdump -S seg

    可以查看到Backtrace得到个6个地址中第2个地址(0x400795)输出为test1的内部调用,如下

linux下使用backtrace函数捕定位段错误问题

至此,可初步定位到段错误的地址。

另外总线错误可使用SEGBUS信号捕捉。