您的位置:首页 > 运维架构 > Linux

跟踪程序异常退出

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)在程序内加入信号响应函数,函数的作用是退出时打印栈信息。以下是示例程序:  
 
#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( );
}

   2) 反汇编程序,并生成文件dump

objdump -d ./a.out >> dump
   3) 编译运行,程序报错

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]
  4) 查看报错信息

    【./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