一、core dump文件生成
Core文件其實就是內存的映像,當程序崩潰時,存儲內存的相應信息,主用用于對程序進行調試。當程序崩潰時便會產生core文件,其實準確的應該說是core dump 文件,默認生成位置與可執行程序位于同一目錄下。
1.查看core文件生成是否開啟
ulimit -a

第一行core file size 如果是0表示沒有打開,unlimited表示不限制產生文件大小。
ulimit -c 查看也可以

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命令獲取是誰產生的

上邊的core.20458文件是我執行kill -s SIGSEGV $$生成的
因此執行
gdb /bin/bash -c core.20458

圖中顯示我沒有符號表,需要把符號表拷貝到相應的bin目錄下,例如如果是openGauss數據庫產生的core的話,就找到相應的符號表的包解壓出來,把gaussdb.symbol拷貝到數據庫的bin/下。(根據提示放到指定位置就可以)
(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

使用GDB調試
gdb ysla

(1)列出代碼
(gdb) l
列出代碼,相當于list,從第一行開始例出原碼

直接回車會重復上一次的操作
(2)設置斷點
(gdb) gdb 13

(3)查看斷點信息
(gdb) info break

(4)運行程序,run命令簡寫
(gdb) r

會在斷點處停住
(5)單條執行,next命令簡寫
(gdb) n

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

(7)打印變量,print簡寫
(gdb) p fp

(8)查看函數堆棧
(gdb) bt

(9)退出函數
(gdb) finish

(10)退出gdb
(gdb) q




