Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1146523
  • 博文数量: 177
  • 博客积分: 761
  • 博客等级: 上士
  • 技术积分: 1518
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-04 22:37
文章分类

全部博文(177)

文章存档

2017年(1)

2016年(3)

2015年(33)

2014年(48)

2013年(60)

2012年(32)

分类: LINUX

2014-10-04 16:54:07

原文地址:跟踪程序异常退出 作者:大隐隐于床

程序出现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

注意最后两行。这就是出错的函数。

 

阅读(1079) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~