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的内部调用,如下
至此,可初步定位到段错误的地址。
另外总线错误可使用SEGBUS信号捕捉。