1. 程式人生 > >使用gdb和core dump如何快速定位到段錯誤

使用gdb和core dump如何快速定位到段錯誤

這篇文章主要介紹的就是在產生段錯誤時如何快速定位到錯誤的位置?

 一.一個簡單的關於段錯誤的例項

  1. #include<stdio.h>
  2. #include<signal.h>
  3. void handler(int sign)  
  4. {  
  5.     printf("pid is %d,signnum is %d\n",getpid(),sign);  
  6. }  
  7. int main()  
  8. {  
  9.     int i=1;  
  10.     for(;i<=31;i++)  
  11.     {  
  12.         //signal(i,handler);
  13.     }  
  14.     int
     *p=(int *)10;   
  15.     *p=10;  
  16.     return 0;  
  17. }  

    對該程式程序編譯連結執行之後會產生如下錯誤:

    在上面的錯誤中可以看到core dumped,那仫什仫是core dumped呢?

 二.什仫是core dump?

   core的意思是核心,dumped的意思就是丟擲,轉儲,core dumped就是核心轉儲的意思。當一個程序異常退出前,該程序會丟擲當時該程式程序的記憶體詳細情況儲存在硬碟上,檔名通常是core,這就叫core dump。

   程序異常終止通常是因為程式碼存在BUG,比如非法記憶體訪問導致段錯誤,事後可以用偵錯程式檢查core檔案以查清錯誤原因,這叫做事後除錯

 三.如何使用gdb和core dumped快速定位到錯誤位置?

   一個程序允許產生多大的core檔案取決於程序的Resource Limit(這個資訊儲存 在PCB中)。預設是不允許產生core檔案的,因為core檔案中可能包含使用者密碼等敏感資訊,不安全。在開發除錯階段可以用ulimit命令改變這個限制,允許產生core檔案。

   1.core檔案是核心生成的,那某一個程序因為段錯誤而崩潰的時候的記憶體映像很大,那必然會生成一個很大的core檔案,我們可以使用umilit -a顯示當前shell下的各種軟硬體的上限。

   我們也可以通過ulimit命令來設定生成core檔案的大小,

   例如:(1).ulimit -c unlimited,這裡就是設定生成的core檔案無大小限制。

         (2).ulimit -c [size],表示設定生成的core檔案的最大上限為size。

   eg1:ulimit -a

 

   eg2:使用ulimit -c 1024修改core檔案的最大上限 

 

  2.在修改了core檔案的上限之後此時再次對該檔案進行編譯連結執行就會產生一個core.xxx的檔案,該檔案非常大

  3.使用gdb和core dumped除錯該檔案:gdb 程式名 core.xxx,只要輸入gdb signal core.3250即可,在進入gdb之後可以使用where查找出錯的位置也可以使用core-file core.xxx來查詢錯誤的位置。

   (1).使用core-file core.xxx的形式定位錯誤

   

    (2).在gdb狀態下使用where來定位錯誤

轉載地址:http://blog.csdn.net/oneday_789/article/details/72840850

訊號主要是用於不同程序之間進行通訊的機制,程序之間的相互協作也正是通過傳送訊號來完成的,而訊號的本質就是修改PCB中關於訊號變數的某個位元位(至於為什麼是一個位元位,隨後就會做出解釋)

檢視當前系統定義的訊號列表:kill -l

請看仔細咯,上面的訊號量列表個數並不是64個,而是62個

訊號分類

普通訊號:1——31號訊號

實時訊號:34——64號訊號

在我們的學習中主要研究的是1——31號普通訊號,因此在對應的PCB中採用點陣圖這個資料結構,就可以表示一個訊號的存在與否,這也解釋了上面的訊號量本質為什麼是修改PCB中管理訊號的變數的一個位元位

背景知識

前臺程序:基本上不和使用者互動,優先順序稍微低一些

後臺程序:需要和使用者進行互動,需要較高響應速度,優先級別稍微高一些

訊號產生的條件

(1)使用者在終端按下某些組合鍵,終端驅動程式會發送訊號給前臺訊號;

(2)硬體異常產生訊號,有硬體檢測併發送給核心,然後由核心向當前程序傳送訊號;

程序終止的根本原因就是因為收到訊號

(3)使用kill命令傳送訊號給其他程序;

訊號的三種處理方式

(1)忽略此訊號(大多數訊號都可以使用這種方式處理)

特例:SIGKILL和SIGSTOP

原因:他們向超級使用者提供一種使程序終止或停止的可靠方法,同時,如果忽略某些由硬體異常產生的訊號,則程序的行為是未定義的。

(2)直接執行程序對於該訊號的預設動作(與訊號的種類有關,大多數會直接終止該程序)

(3)捕捉訊號(執行自定義動作,使用signal函式,而要做到這一點必須呼叫handler使用者函式,可以執行使用者希望做的事情)

特例:不能捕捉SIGKILL和SIGSTOP函式

原因:試想一下,如果所有的訊號都可以被捕捉,那麼當非法使用者入侵時就會導致程序永遠殺不掉,因此係統在最初設計這些訊號時,就特意留出了不能被捕捉的訊號。

#include <signal.h>
 typedef void (*sighandler_t)(int);                    //具體執行動作的函式
sighandler_t signal(int signum, sighandler_t handler); //第一個引數,訊號編號,第二個引數,訊號執行的動作


程式碼示例:

#include<stdio.h>
#incldue<stdlib.h>
#include<signal.h>

void* mysig(int sig)
{
     printf("pid: %d,sig is %d\n",getpid(), sig);
}

int main()
{
     signal(2,mysig);
     retrurn 0;
}


檢視當前的mysignal程序狀態

利用core dump(核心轉儲)定位錯誤地方

error:error.c
        gcc -o error error.c
.PHONY:clean
clean:
        rm -f error
#include<stdio.h>

int main()
{
        int* p=10;
        *p=5;
        printf("%d",(int)p);
        return 0;
}

執行結果:

先試用ulimit -a來檢視當前系統下各種資源的上限

系統預設的大小是0,而core dump的作用是,當一個程序正在執行,突然收到一場錯誤時,作業系統為了方便除錯,將記憶體中的程序資料儲存到硬碟中。但是以死迴圈的形式將錯誤不停的儲存時,後果可想而知。

修改ulimit -c [size]修改core dump的大小

修改core檔案之後,再次編譯檢視時,就會有一個很大的core檔案產生(其後的數字表示程序號)

使用core-file core.xxxx定位錯誤


轉載出處:http://m.blog.csdn.net/article/details?id=72848372