如何捕捉並分析SIGSEGV的現場


  linux下程序對SIGSEGV信號的默認處理方式是產生coredump並終止程序,可以參考man 7 signal

       Signal     Value     Action   Comment
       ──────────────────────────────────────────────────────────────────────
       SIGHUP        1       Term    Hangup detected on controlling terminal
                                     or death of controlling process
       SIGINT        2       Term    Interrupt from keyboard
       SIGQUIT       3       Core    Quit from keyboard
       SIGILL        4       Core    Illegal Instruction
       SIGABRT       6       Core    Abort signal from abort(3)
       SIGFPE        8       Core    Floating point exception
       SIGKILL       9       Term    Kill signal
       SIGSEGV      11       Core    Invalid memory reference
       SIGPIPE      13       Term    Broken pipe: write to pipe with no
                                     readers
       SIGALRM      14       Term    Timer signal from alarm(2)
       SIGTERM      15       Term    Termination signal
       SIGUSR1   30,10,16    Term    User-defined signal 1
       SIGUSR2   31,12,17    Term    User-defined signal 2
       SIGCHLD   20,17,18    Ign     Child stopped or terminated
       SIGCONT   19,18,25    Cont    Continue if stopped
       SIGSTOP   17,19,23    Stop    Stop process
       SIGTSTP   18,20,24    Stop    Stop typed at terminal
       SIGTTIN   21,21,26    Stop    Terminal input for background process
       SIGTTOU   22,22,27    Stop    Terminal output for background process

  對於Action的描述

       The entries in the "Action" column of the tables below specify the
       default disposition for each signal, as follows:

       Term   Default action is to terminate the process.

       Ign    Default action is to ignore the signal.

       Core   Default action is to terminate the process and dump core (see
              core(5)).

       Stop   Default action is to stop the process.

       Cont   Default action is to continue the process if it is currently
              stopped.

  可以看到產生core這個動作的信號不止SIGSEGV這一個。通常程序中有對內存的Invalid reference就會產生SIGSEGV,具體描述見http://www.cnblogs.com/thammer/p/4737371.html 。

 

  分析段錯誤的方法

    1.直接使用gdb

      如果是容易重現的SIGSEGV直接gdb掛着運行,產生SIGSEGV時gdb會停止並打印提示,這時直接敲入命令bt查看程序此時的函數調用棧幀就可以定位到是哪個函數在什么樣的調用情況下出現段錯誤。

    2.使用core文件+gdb

      在程序收到SIGSEGV時會產生coredump,core文件就是異常進程在發生異常的那一個時刻的進程內存上下文和cpu寄存器的信息。

      首先,設置core文件大小 ulimit -c XXXX,XXXX就是允許產生的core文件大小,通常設置為unlimited,不限定大小

      然后,運行程序直至產生core文件,名字一般是core.xxx,xxx為程序進程號,不同發行版本可能有不同的命名規則

      然后,運行gdb,敲入命令 core-file corefile-name,再bt即可

    3.注冊SIGSEGV信號處理函數,在處理函數里面使用一些堆棧回溯的函數打印棧幀信息。

      A.使用glibc帶的函數backtrace backtrace_symbols backtrace_symbols_fd打印

       void SigSegv_handler(int signo)
       {
           int j, nptrs;
           void *buffer[BT_BUF_SIZE];
           char **strings;

           nptrs = backtrace(buffer, BT_BUF_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);
       exit(-1); }

 

     backtrace_symbols 和backtrace_symbols_fd不同在於后者將打印輸入到一個fd指定的文件里面。

     它有一定的限制:

     

       These functions make some assumptions about how a function's return
       address is stored on the stack.  Note the following:

       *  Omission of the frame pointers (as implied by any of gcc(1)'s
          nonzero optimization levels) may cause these assumptions to be
          violated.

       *  Inlined functions do not have stack frames.

       *  Tail-call optimization causes one stack frame to replace another.

       The symbol names may be unavailable without the use of special linker
       options.  For systems using the GNU linker, it is necessary to use
       the -rdynamic linker option.  Note that names of "static" functions
       are not exposed, and won't be available in the backtrace.

      對優化的程序可能失效

      對inline函數失效

      對static函數僅能打印函數地址

      對tail-call優化的函數失效

      編譯時需要加入 -rdynamic

 

              B.還有其他方法或接口做類似backtrace的事情,以后補充

        


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM