Linux下core dump (段錯誤)

在linux下開發時,如果程序突然崩潰了,也沒有任何日誌。這時可以查看core文件。從core文件中分析原因,通過gdb看出程序掛在哪裏,分析前後的變量,找出問題的原因。

Core Dump

當程序運行的過程中異常終止或崩潰,操作系統會將程序當時的內存狀態記錄下來,保存在一個文件中,這種行爲就叫做Core Dump(中文有的翻譯成“核心轉儲”)。我們可以認爲 core dump 是“內存快照”,但實際上,除了內存信息之外,還有些關鍵的程序運行狀態也會同時 dump 下來,例如寄存器信息(包括程序指針、棧指針等)、內存管理信息、其他處理器和操作系統狀態和信息。core dump 對於編程人員診斷和調試程序是非常有幫助的,因爲對於有些程序錯誤是很難重現的,例如指針異常,而 core dump 文件可以再現程序出錯時的情景。

相關設置

如果沒有進行core dump 的相關設置,默認是不開啓的。可以通過ulimit -c查看是否開啓。如果輸出爲0,則沒有開啓,需要執行ulimit -c unlimited開啓core dump功能。

ulimit

ulimit命令用來限制系統用戶對shell資源的訪問。限制 shell 啓動進程所佔用的資源,支持以下各種類型的限制:所創建的內核文件的大小、進程數據塊的大小、Shell 進程創建文件的大小、內存鎖住的大小、常駐內存集的大小、打開文件描述符的數量、分配堆棧的最大大小、CPU 時間、單個用戶的最大線程數、Shell 進程所能使用的最大虛擬內存。同時,它支持硬資源和軟資源的限制。

ulimit相關選項如下:

-a:顯示目前資源限制的設定;
-c <core文件上限>:設定core文件的最大值,單位爲區塊;
-d <數據節區大小>:程序數據節區的最大值,單位爲KB;
-f <文件大小>:shell所能建立的最大文件,單位爲區塊;
-H:設定資源的硬性限制,也就是管理員所設下的限制;
-m <內存大小>:指定可使用內存的上限,單位爲KB;
-n <文件數目>:指定同一時間最多可開啓的文件數;
-p <緩衝區大小>:指定管道緩衝區的大小,單位512字節;
-s <堆疊大小>:指定堆疊的上限,單位爲KB;
-S:設定資源的彈性限制;
-t <CPU時間>:指定CPU使用時間的上限,單位爲秒;
-u <程序數目>:用戶最多可開啓的程序數目;
-v <虛擬內存大小>:指定可使用的虛擬內存上限,單位爲KB。

 core文件的名稱和生成路徑:

沒有進行設置的話,默認生成的core文件不帶其它任何擴展名稱,全部命名爲core。新的core文件生成將覆蓋原來的core文件 。 可對core文件的名稱和生成路徑進行相關配置,如下:

  • /proc/sys /kernel/core_uses_pid可以控制core文件的文件名中是否添加pid作爲擴展。文件內容爲1,表示添加pid作爲擴展名,生成的 core文件格式爲core.xxxx;爲0則表示生成的core文件同一命名爲core。

  • proc/sys/kernel/core_pattern可以控制core文件保存位置和文件名格式。

以下是參數列表:

%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 添加命令名 

更多請參考core dump file.

示例:

會產生錯誤的代碼如下:

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <sys/time.h>
 4 #include <sys/resource.h>
 5 
 6 #define CORE_SIZE 500 * 1024 * 1024
 7 
 8 int main(){
 9     struct rlimit rlmt;
10     if (getrlimit(RLIMIT_CORE, &rlmt) == -1) {
11         return -1;
12     }
13     printf("Before set rlimit core dump current is:%d, max is:%d\n", (int)rlmt.rlim_cur, (int)rlmt.rlim_max);
14 
15     rlmt.rlim_cur = (rlim_t)CORE_SIZE;
16     rlmt.rlim_max = (rlim_t)CORE_SIZE;
17 
18     if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
19         return -1;
20     }
21 
22     if (getrlimit(RLIMIT_CORE, &rlmt) == -1) {
23         return -1;
24     }
25     printf("After set rlimit core dump current is:%d, max is:%d\n", (int)rlmt.rlim_cur, (int)rlmt.rlim_max);
26 
27     // 對空指針指向的內存區域寫,會發生段錯誤 -->產生core文件
28     int *null_ptr = NULL;
29     *null_ptr = 10;
30 
31     return 0;
32 }

使用 gcc 編譯源文件,加上 -g 以增加調試信息;執行會產生錯誤,生成core文件。

這裏寫圖片描述

執行gdb <program> core後輸出信息如下圖:
這裏寫圖片描述
gdb <program> core: 用gdb同時調試一個運行程序和core文件,core是程序非法執行後core dump後產生的文件。可以看到程序的問題是core_dump.c文件中第31行對一個空指針賦值的錯誤提示。

 

轉自:https://www.cnblogs.com/s-lisheng/p/11278193.html

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章