1. 程式人生 > >Linux下core dump

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 新增命令名 

示例:

會產生錯誤的程式碼如下:

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>

#define CORE_SIZE 500 * 1024 * 1024


int main(){
    struct rlimit rlmt;
    if (getrlimit(RLIMIT_CORE, &rlmt) == -1) {
        return -1;
    }
    printf("Before set rlimit core dump current is:%d, max is:%d\n", (int)rlmt.rlim_cur, (int)rlmt.rlim_max);

    rlmt.rlim_cur = (rlim_t)CORE_SIZE;
    rlmt.rlim_max = (rlim_t)CORE_SIZE;

    if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
        return -1;
    }

    if (getrlimit(RLIMIT_CORE, &rlmt) == -1) {
        return -1;
    }
    printf("After set rlimit core dump current is:%d, max is:%d\n", (int)rlmt.rlim_cur, (int)rlmt.rlim_max);


    // 對空指標指向的記憶體區域寫,會發生段錯誤 -->產生core檔案
    int *null_ptr = NULL;
    *null_ptr = 10;

    return 0;
}

使用 gcc 編譯原始檔,加上 -g 以增加除錯資訊;執行會產生錯誤,生成core檔案。 這裡寫圖片描述

執行gdb <program> core後輸出資訊如下圖: 這裡寫圖片描述

gdb <program> core: 用gdb同時除錯一個執行程式和core檔案,core是程式非法執行後core dump後產生的檔案。