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

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

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

   

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

   

    對該程序進程編譯鏈接運行之後會產生如下錯誤:

    在上面的錯誤中可以看到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

發佈了115 篇原創文章 · 獲贊 48 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章