1. 程式人生 > >段錯誤(核心已轉儲)問題的分析方法

段錯誤(核心已轉儲)問題的分析方法

問題現象

今天在研究linux kernel中typedef的用法時,寫了一個程式test_typedef.c,內容如下:

#include<stdio.h>

typedef int size;
typedef unsigned int word;
typedef char line[81];
typedef void (*printStr)(line text);
typedef printStr * pprintStr;
typedef char * pstr;

void printText(line text){
    printf("%s\n", text);
}

void
* pppPrintText(line text){ printf("%s\n", text); } pprintStr pprintText(){ //return &printText; printStr temp = printText; return (printStr *)temp; } /*void (*pprintText)(line text){ printf("%s\n", text); }*/ void main(){ size i=10; word w = 20; line text; printf
("%d, %d, %d\n",i, w, sizeof(text)/sizeof(char)); printStr printFun = printText; pprintStr pprintFun = pprintText(); printFun("test typedef"); //((printStr)pprintFun)("test pointer typedef"); (*pprintFun)("test pointer typedef"); char string[4] = "abc"; pstr p1 = string; const
char *p2 = string; p1++; p2++; printf("%s, %s\n", p1, p2); }

加上37行的程式碼(*pprintFun)(“test pointer typedef”);後,通過gcc –o typedef test_typdef.c命令編譯成typedef可執行檔案後執行,出現段錯誤:

這裡寫圖片描述

之前也遇見過“段錯誤(核心已轉儲)”(Segmentation fault(core dumped)),但是沒有進行分析,今天藉著這個機會學習一下這類問題的分析方法。

段錯誤的分析方法

段錯誤一般藉助於可除錯(使用-g選項進行編譯)的原程式和核心轉儲後的core file來進行分析,如針對我寫的程式,其步驟為:

  • gcc –g –o typedef test_typedef.c (生成可除錯的可執行程式)
  • ./typedef (產生段錯誤,生成core file)
  • gdb –c core_file typdef (使用core file除錯產生段錯誤的可執行程式)
  • 在gdb除錯環境中執行bt或where命令定位到問題行

按如上步驟對typedef可執行程式的分析結果如下:

這裡寫圖片描述

由上圖可以看出,通過core file定位出來的問題程式碼行也是37行,說明分析結果的準確性。

core file的產生

core file檔案是在程式異常退出時產生的,程式的異常退出往往是通過訊號(signal)產生的,但並不是所有的訊號都能夠產生core file,在signal.h的標頭檔案中定義了哪些signal可以產生core file,如下:

這裡寫圖片描述
這裡寫圖片描述

上圖中所有default action為coredump的中斷訊號都可以產生core file。
除了中斷訊號必須能夠產生coredump外,還必須進行如下設定:

  • ulimit –c unlimited (設定core file的大小,相當於使能core file的生成)
  • ulimit unlimited (設定file的大小)

其他問題

1. core file存放在哪個目錄
存放core file一般存放在程序的當前工作目錄,一般就是當初發出命令啟動該程序時所在的目錄。但如果是通過指令碼啟動,則指令碼可能會修改當前目錄,這時程序真正的當前目錄就會與當初執行指令碼所在目錄不同。這時可以檢視“/proc/pid/cwd”符號連結的目標來確定程序真正的當前目錄地址。

2. core file的檔名
一般core file的檔名即為core,可能通過

echo "1" > /proc/sys/kernel/core_uses_pid

將core file的檔名改為core.pid

3. 如何修改core file的檔名格式和儲存位置
/proc/sys/kernel /core_pattern可以控制core檔案儲存位置和檔名格式。可通過以下命令修改此檔案:

echo  "/corefile/core-%e-%p-%t" >/proc/sys/kernel /core_pattern

可以將core檔案統一生成到/corefile目錄下,產生的檔名為core-命令名-pid-時間戳
以下是引數列表:
%p - insert pid into filename 新增pid
%u - insert current uid into filename 添加當前uid
%g - insert current gid into filename 添加當前gid
%s - insert signal that caused the coredump into the filename 新增導致產生core的訊號
%t - insert UNIX time that the coredump occurred into filename 新增core檔案生成時的unix時間
%h - insert hostname where the coredump happened into filename 新增主機名
%e - insert coredumping executable name into filename 新增命令名

4. 如果你當初是以使用者A運行了某個程式,但在ps裡看到的這個程式的使用者卻是B的話,那麼這些程序就是呼叫了seteuid了。為了能夠讓這些程序生成core dump,需要將/proc/sys/fs/suid_dumpable 檔案的內容改為1(一般預設是0)

參考技術文章