跟踪程序异常退出
2016-03-30 17:32
519 查看
程序出现SIGSEGV、SIGABRT、SIGBUS等等错误时,都会默认退出。
这个时候一般用两种方法来跟踪最为快捷:
1 gdb调试core文件,这种方法最简单,只简单描述一下。
1) 在编译时加入-g参数
2) ulimit -c unlimited
这样在程序段错语时会生成core文件
3) gdb ./a.out 载入程序
4) core-file core 载入core文件
backtrace或bt 查看栈信息
where 显示程序在哪一行当掉的,在哪个函数中
frame N 移动到指定帧,查看具体信息
2 但有的时候无法生成core文件,或者core文件无法查看到栈信息,那就要用到以下方法。
*注:可以直接加到程序内。特别是对长期运行有守护的程序。
1)在程序内加入信号响应函数,函数的作用是退出时打印栈信息。以下是示例程序:
2) 反汇编程序,并生成文件dump
3) 编译运行,程序报错
4) 查看报错信息
【./a.out [0x804852d]】 在栈顶,是信号响应函数,不用管。
注意【./a.out [0x80485d6]】并在dump文件中查找80485d6这个地址:
注意最后两行。这就是出错的函数。
出处:http://blog.chinaunix.net/uid-20692625-id-1892926.html
这个时候一般用两种方法来跟踪最为快捷:
1 gdb调试core文件,这种方法最简单,只简单描述一下。
1) 在编译时加入-g参数
2) ulimit -c unlimited
这样在程序段错语时会生成core文件
3) gdb ./a.out 载入程序
4) core-file core 载入core文件
backtrace或bt 查看栈信息
where 显示程序在哪一行当掉的,在哪个函数中
frame N 移动到指定帧,查看具体信息
2 但有的时候无法生成core文件,或者core文件无法查看到栈信息,那就要用到以下方法。
*注:可以直接加到程序内。特别是对长期运行有守护的程序。
1)在程序内加入信号响应函数,函数的作用是退出时打印栈信息。以下是示例程序:
#include "stdlib.h" #include "stdio.h" #include "signal.h" #include "execinfo.h" void fun_dump( int no) { char _signal[64][32] = { "1: SIGHUP", "2: SIGINT", "3: SIGQUIT", "4: SIGILL", "5: SIGTRAP", "6: SIGABRT", "7: SIGBUS", "8: SIGFPE", "9: SIGKILL", "10: SIGUSR1", "11: SIGSEGV", "12: SIGUSR2", "13: SIGPIPE", "14: SIGALRM", "15: SIGTERM", "16: SIGSTKFLT", "17: SIGCHLD", "18: SIGCONT", "19: SIGSTOP", "20: SIGTSTP", "21: SIGTTIN", "22: SIGTTOU", "23: SIGURG", "24: SIGXCPU", "25: SIGXFSZ", "26: SIGVTALRM", "27: SIGPROF", "28: SIGWINCH", "29: SIGIO", "30: SIGPWR", "31: SIGSYS", "34: SIGRTMIN", "35: SIGRTMIN+1", "36: SIGRTMIN+2", "37: SIGRTMIN+3", "38: SIGRTMIN+4", "39: SIGRTMIN+5", "40: SIGRTMIN+6", "41: SIGRTMIN+7", "42: SIGRTMIN+8", "43: SIGRTMIN+9", "44: SIGRTMIN+10", "45: SIGRTMIN+11", "46: SIGRTMIN+12", "47: SIGRTMIN+13", "48: SIGRTMIN+14", "49: SIGRTMIN+15", "50: SIGRTMAX-14", "51: SIGRTMAX-13", "52: SIGRTMAX-12", "53: SIGRTMAX-11", "54: SIGRTMAX-10", "55: SIGRTMAX-9", "56: SIGRTMAX-8", "57: SIGRTMAX-7", "58: SIGRTMAX-6", "59: SIGRTMAX-5", "60: SIGRTMAX-4", "61: SIGRTMAX-3", "62: SIGRTMAX-2", "63: SIGRTMAX-1", "64: SIGRTMAX" }; void *stack_p[10]; char **stack_info; int size; size = backtrace( stack_p, sizeof(stack_p)); stack_info = backtrace_symbols( stack_p, size); if( no >= 1 && no <= 64) printf("[%s] %d stack frames.\n", _signal[no-1], size); else printf("[No infomation %d] %d stack frames.\n", no, size); int i = 0; for( ; i < size; i++) printf("%s\n", stack_info[i]); free( stack_info); //free anything fflush(NULL); exit(0); } int fun_err() { char *p = 0x0 ; *p = 'a'; } int main( int argc, char *argv[]) { signal( SIGSEGV, fun_dump); fun_err( ); } |
objdump -d ./a.out >> dump |
BTC:/home/code/test # gcc -g main.c BTC:/home/code/test # ./a.out [11: SIGSEGV] 5 stack frames. ./a.out [0x804852d] [0xffffe420] ./a.out [0x80485d6] /lib/libc.so.6(__libc_start_main+0xdc) [0xb7e6587c] ./a.out [0x8048491] |
【./a.out [0x804852d]】 在栈顶,是信号响应函数,不用管。
注意【./a.out [0x80485d6]】并在dump文件中查找80485d6这个地址:
080485ac <main>: 80485ac: 8d 4c 24 04 lea 0x4(%esp),%ecx 80485b0: 83 e4 f0 and $0xfffffff0,%esp 80485b3: ff 71 fc pushl 0xfffffffc(%ecx) 80485b6: 55 push %ebp 80485b7: 89 e5 mov %esp,%ebp 80485b9: 51 push %ecx 80485ba: 83 ec 14 sub $0x14,%esp 80485bd: c7 44 24 04 14 85 04 movl $0x8048514,0x4(%esp) 80485c4: 08 80485c5: c7 04 24 0b 00 00 00 movl $0xb,(%esp) 80485cc: e8 0f fe ff ff call 80483e0 <signal@plt> 80485d1: e8 c1 ff ff ff call 8048597 <fun_err> 80485d6: 83 c4 14 add $0x14,%esp |
出处:http://blog.chinaunix.net/uid-20692625-id-1892926.html
相关文章推荐
- Linux socket 初步
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- Linux 下无损图片压缩小工具介绍