第一时间捕获段错误(segment fault)的详细信息
来源:互联网 发布:西安交通大学网络学校 编辑:程序博客网 时间:2024/05/01 03:10
不使用gdb也能捕获段错误的详细信息,事实上,使用gdb是一件很麻烦的事情!第一,gdb功能太过强大,诊断个段错误真是大材小用,如果不会用还要学...其次,很多系统并没有安装这个工具。因此最好的办法就是“自报死因”。在Linux中,这是很容易做到的,本文给出一种方式。
1.2.siginfo中对于SIGSEGV而言其si_addr字段(由宏定义)保存段错误地址
1.3.backtrace_symbols/backtrace是很好的调试函数
1.4.rdynamic编译参数加载所有的符号
1.5.Linux的信号处理函数在用户栈上堆叠执行(详情参阅Linux源码setup_frame函数)。
编译:
gcc segftest.c -o segftest -rdynamic
执行segftest的输出:
./segftest(test+0x3f) [0x400a63]
/lib/libc.so.6(+0x321e0) [0x7fe7ec9441e0]
/lib/libc.so.6(memcpy+0x37) [0x7fe7ec991787]
./segftest(todo2+0x22) [0x400ad2]
./segftest(todo1+0x18) [0x400aec]
./segftest(main+0x6a) [0x400b58]
/lib/libc.so.6(__libc_start_main+0xfd) [0x7fe7ec930c4d]
./segftest() [0x400969]
很是一目了然!因此在任意程序中调用下列的setuptrap即可在第一时间得到段错误的详细信息,包括引发段错误的地址,以及函数调用堆栈。
1.理解“自报死因”这个机制的前提
1.1.SIGSEGV信号是可以捕获的1.2.siginfo中对于SIGSEGV而言其si_addr字段(由宏定义)保存段错误地址
1.3.backtrace_symbols/backtrace是很好的调试函数
1.4.rdynamic编译参数加载所有的符号
1.5.Linux的信号处理函数在用户栈上堆叠执行(详情参阅Linux源码setup_frame函数)。
2.测试的例子
以下为测试程序源码segftest.c:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <execinfo.h>#define SIZE 1000void *buffer[SIZE];void todo1(char *buf);void todo2(char *buf);void test(int n,struct siginfo *siginfo,void *myact){ int i, num; char **calls; printf("Fault address:%X\n",siginfo->si_addr); num = backtrace(buffer, SIZE); calls = backtrace_symbols(buffer, num); for (i = 0; i < num; i++) printf("%s\n", calls[i]); exit(1);} void todo2(char *buf){ memcpy(buf, "aaaa", 4); //引发段错误}void todo1(char *buf){ todo2(buf);}int main(int argc, char **argv){ char *no_alloc = (char *)0x1234; //未分配的内存 struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags=SA_SIGINFO; act.sa_sigaction=test; sigaction(SIGSEGV,&act,NULL); todo1(no_alloc);}
编译:
gcc segftest.c -o segftest -rdynamic
执行segftest的输出:
./segftest(test+0x3f) [0x400a63]
/lib/libc.so.6(+0x321e0) [0x7fe7ec9441e0]
/lib/libc.so.6(memcpy+0x37) [0x7fe7ec991787]
./segftest(todo2+0x22) [0x400ad2]
./segftest(todo1+0x18) [0x400aec]
./segftest(main+0x6a) [0x400b58]
/lib/libc.so.6(__libc_start_main+0xfd) [0x7fe7ec930c4d]
./segftest() [0x400969]
很是一目了然!因此在任意程序中调用下列的setuptrap即可在第一时间得到段错误的详细信息,包括引发段错误的地址,以及函数调用堆栈。
#include <signal.h>#include <execinfo.h>#define SIZE 1000void *buffer[SIZE];void fault_trap(int n,struct siginfo *siginfo,void *myact){ int i, num; char **calls; printf("Fault address:%X\n",siginfo->si_addr); num = backtrace(buffer, SIZE); calls = backtrace_symbols(buffer, num); for (i = 0; i < num; i++) printf("%s\n", calls[i]); exit(1);}void setuptrap(){ struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags=SA_SIGINFO; act.sa_sigaction=fault_trap; sigaction(SIGSEGV,&act,NULL);}
- 第一时间捕获段错误(segment fault)的详细信息
- 第一时间捕获段错误(segment fault)的详细信息
- 捕获Linux段错误(Segment fault)并且打印错误堆栈
- 【Segment Fault】段错误解析
- 段错误(Segment Fault!)莫名的问题 by fish
- 段错误(Segment Fault!)莫名的问题
- 段错误(segment fault)的几种原因
- segment fault 段错误 (core dumped)的起因分析!
- 用gdb检查段错误(segment fault)
- 用gdb检查段错误(segment fault)
- 用gdb检查段错误(segment fault)
- 用gdb检查段错误(segment fault)
- segment fault 段错误各种原因
- c++中的段错误(segment fault)
- Linux 段错误调试Segment Fault
- linnx内核出现段错误(segment fault)的调试方法
- 利用linux信号机制调试段错误(Segment fault)
- 使用gdb调试段错误(segment fault)
- 从尾到头输出链表
- tomcat配置
- VS2010中的调试技巧
- Grid总结
- 窗体前置的应用
- 第一时间捕获段错误(segment fault)的详细信息
- 模板特化和偏特化
- 新浪微博api调用android DEMO (完整版)
- 笔记本设置wifi热点
- 海边纪事
- hadoop 最小化运行
- 中国移动举行“移动生活卡”首发仪式
- JAVA设计模式-State
- flex组件生命周期对mxml和as的影响_悄悄俏俏