结合文章http://blog.csdn.net/zahuopuboss/article/details/46519697
与信号处理
在程序出现段错的时候,打印函数调用链
#include <execinfo.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> void trace(int signo) { int j, nptrs; #define SIZE 100 void *buffer[100]; char **strings; printf("signo: %d\n", signo); nptrs = backtrace(buffer, SIZE); printf("backtrace() returned %d addresses\n", nptrs); /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO) * would produce similar output to the following: */ strings = backtrace_symbols(buffer, nptrs); if (strings == NULL) { perror("backtrace_symbols"); exit(EXIT_FAILURE); } for (j = 0; j < nptrs; j++) printf("%s\n", strings[j]); free(strings); if (SIGSEGV == signo || SIGQUIT == signo) { exit(0); } } void segfault(void) { int *p = NULL; *p = 1; } int main(int argc, char *argv[]) { signal(SIGSEGV, trace); signal(SIGINT, trace); signal(SIGQUIT, trace); while (1) { sleep(1); if (time(0) % 7 == 0) { segfault(); } } return 0; }
编译方法 gcc -rdynamic seg.c -o seg -g
段错信息
signo: 11 backtrace() returned 6 addresses ./seg(trace+0x3c) [0x400aac] /lib64/libc.so.6() [0x3c39635690] ./seg(segfault+0x10) [0x400b64] ./seg(main+0x83) [0x400bef] /lib64/libc.so.6(__libc_start_main+0xf5) [0x3c39621b45] ./seg() [0x4009a9]
使用 objdump -d seg 查看出错地址 0x400b64 是一个赋值操作
0000000000400b54 <segfault>: 400b54: 55 push %rbp 400b55: 48 89 e5 mov %rsp,%rbp 400b58: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp) 400b5f: 00 400b60: 48 8b 45 f8 mov -0x8(%rbp),%rax 400b64: c7 00 01 00 00 00 movl $0x1,(%rax) 400b6a: 5d pop %rbp 400b6b: c3 retq
使用 addr2line 0x400b64 -e seg -afs 查看段错函数和对应的代码行数
0x0000000000400b64 segfault seg.c:41