coredump檔案生成,以及GDB工具使用

T1YSL發表於2021-11-25

一、core dump檔案生成
Core檔案其實就是記憶體的映像,當程式崩潰時,儲存記憶體的相應資訊,主用用於對程式進行除錯。當程式崩潰時便會產生core檔案,其實準確的應該說是core dump 檔案,預設生成位置與可執行程式位於同一目錄下。
1.檢視core檔案生成是否開啟

ulimit -a

image.png
第一行core file size 如果是0表示沒有開啟,unlimited表示不限制產生檔案大小。

ulimit -c 檢視也可以

image.png

2.開啟關閉core

關閉或阻止core檔案生成:
$ulimit -c 0
開啟core檔案生成且不限制:
$ulimit -c unlimited

如果生成的資訊超過此大小,將會被裁剪,最終生成一個不完整的core檔案。
在除錯這樣的core檔案的時候,gdb會提示錯誤。
臨時設定(如下設定2G,單位為kbyte)

ulimit -c 4194304

3.修改core檔名稱
(1)臨時修改:
修改/proc/sys/kernel/core_pattern檔案,但/proc目錄本身是動態載入的,每次系統重啟都會重新載入,因此這種方法只能作為臨時修改。

使用root使用者修改core檔案生成名和路徑:生成的core檔案儲存在/tmp/corefile 目錄下,且core檔名為:
core-命令名-pid-時間戳(需系統支援修改該檔案)

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

可以將core檔案統一生成到/corefile目錄下,產生的檔名為core-命令名-pid-時間戳
以下是引數列表:

%p - insert pid into filename 新增pid(程式id)
%u - insert current uid into filename 新增當前uid(使用者id)
%g - insert current gid into filename 新增當前gid(使用者組id)
%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的命令名

(2)永久修改:
可以透過在/etc/sysctl.conf檔案中,對sysctl變數kernel.core_pattern的設定。
#vi /etc/sysctl.conf 然後,在sysctl.conf檔案中新增下面兩行:

kernel.core_pattern = /tmp/corefile/core-%e-%p-%t
kernel.core_uses_pid = 0

kernel.core_uses_pid 這個引數控制core檔案的檔名是否新增pid作為擴充套件,如果這個檔案的內容被配置成1,即使core_pattern中沒有設定%p,最後生成的core dump檔名仍會加上程式ID

使用以下命令,使修改結果馬上生效。

sysctl –p /etc/sysctl.conf

二、GDB工具使用
1.介紹
GDB是一個由GNU開源組織釋出的、UNIX/LINUX作業系統下的、基於命令列的、功能強大的程式除錯工具。
在實際應用中,有兩種除錯方法:線上除錯和離線除錯。

離線除錯適用於開發測試環境,可以自由啟停程式,設定斷點;
線上除錯一般用於現場問題分析,不能隨便啟停程式。
GDB主要來除錯C/C++語言寫的程式,當然也可以除錯其他語言程式

GDB除錯一定要是可執行檔案而不是.c檔案,要用gcc進行編譯

如果除錯PostgreSQL,建議PostgreSQL編譯項的enable-debug開啟,它會開啟除錯符號使偵錯程式跟蹤程式碼。

gcc -g 原始檔.c -o 輸出的目標檔案
gcc -g test.c -o test

-g表示以OS本地格式(stabs,COFF,XCOFF或DWARF 2)產生除錯資訊

2.GDB主要可以做四種事情來幫助你找到bug:

    啟動你的程式,指定任意可以影響程式行為的引數。
    讓你的程式在指定的條件停住.
    測試你的程式停止的時候發生了什麼。
    改變程式內部的變數,來改正程式的錯誤繼續執行。

3.使用GDB

(1)除錯可執行檔案

可以不帶任何引數或選項執行gdb命令,但是最常用的啟動gdb的方式是帶一個或者兩個引數,指定一個可執行檔案來作為引數:

      gdb program(gdb+可執行檔名稱)

(2)分析core檔案

也可以再gdb檔案後面指定可執行檔案 和 core檔案的名稱:

      gdb program core(gdb + 可執行檔案 +core檔案)

在獲取core檔案時候,可以根據file命令獲取是誰產生的

image.png

上邊的core.20458檔案是我執行kill -s SIGSEGV $$生成的
因此執行

gdb /bin/bash -c core.20458

image.png

(3)根據程式除錯
如果要除錯正在執行的程式,可以指定程式ID作為第二個引數

也可以指定一個程式id作為第二個引數,如果你想除錯一個正在執行的程式:

      gdb program 1234(gdb程式名+程式id)

會附件gdb到程式1234上(除非有一個檔名“1234”;GDB首先檢查core檔案)

4.除錯
常用除錯命令

break [file:]function     設定一個斷點在函式中(在檔案中)
run [arglist]             啟動程式帶上指定的引數
bt    Backtrace:          顯示堆疊
print expr                顯示錶達式的值
c                         繼續執行你的程式(程式停住後,例如:在斷點處停止)
next/n                      執行程式的下一行程式碼(程式停止以後);跨國任何當前行的函式呼叫。
edit [file:]function      檢視當前程式停在哪。
list [file:]function      顯示程式當前停住的程式碼行附近的程式碼
step  單步除錯            執行程式的下一行(程式停住後),進入當前行的函式呼叫的內部,退出函式時使用finish
finish                          結束函式
help [name]               顯示gdb命令的相關資訊。
return                      忽略當前未執行的部分,強制返回
quit                      退出gdb

5.測試

編寫一個測試的檔案ysla.c

#include<stdio.h>
int main()
{
    int a,gw,bw,sw,g,b,r;
    scanf("%d",&a);
    if(a<10&&a>99)
{
    gw=a%10;
    r=a/10;
    sw=r%10;
    bw=r/10;
    b=gw;
    g=bw;
    r=b*100+sw*10+g;
    printf("%d\n",r);
}
    return 0;
}

編譯生成執行檔案

gcc -g ysla.c -o ysla

image.png

使用GDB除錯

gdb ysla

image.png

(1)列出程式碼

(gdb) l

列出程式碼,相當於list,從第一行開始例出原碼
image.png
直接回車會重複上一次的操作

(2)設定斷點

(gdb) gdb 13

image.png

(3)檢視斷點資訊

(gdb) info break

image.png

(4)執行程式,run命令簡寫

(gdb) r

image.png
會在斷點處停住

(5)單條執行,next命令簡寫

(gdb) n

image.png

(6)繼續執行,continue命令簡寫

(gdb) c

image.png

(7)列印變數,print簡寫

(gdb) p fp

image.png

(8)檢視函式堆疊

(gdb) bt

image.png

(9)退出函式

(gdb) finish

image.png

(10)退出gdb

(gdb) q


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69990629/viewspace-2844212/,如需轉載,請註明出處,否則將追究法律責任。

相關文章