1. 程式人生 > >GDB除錯命令(轉載)

GDB除錯命令(轉載)

1.啟動除錯

前置條件:編譯生成執行碼時帶上 -g,如果使用Makefile,通過給CFLAGS指定-g選項,否則除錯時沒有符號資訊。
gdb program //最常用的用gdb啟動程式,開始除錯的方式
gdb program core //用gdb檢視core dump檔案,跟蹤程式core的原因
gdb program pid //用gdb除錯已經開始執行的程式,指定pid即可
gdb attach pid //用gdb除錯已經開始執行的程式,指定pid即可

2.除錯命令
(1)執行命令模式
-batch選項。
比如:列印$pid程序所有執行緒的堆疊並退出。
gdb -ex "set pagination 0" -ex "thread apply all bt" -batch -p $pid

(2).互動模式
run         //執行程式
continue  //中斷後繼續執行到下一個斷點
step        //單步執行,進入函式
next       //單步執行
return    //函式未執行完,忽略未執行的語句,返回。
finish     //函式執行完畢返回。

until      //執行完迴圈
call        //呼叫某一個函式 fun("1234")
(backtrace)bt //顯示棧楨
bt N              //顯示開頭N個棧楨
bt -N            //顯示最後N個棧楨
(frame)f N     //顯示第N層棧楨
list //顯示原始碼
set directory  //設定gdb的工作目錄 
pwd              //當前的工作目錄

(3)反覆執行
continue N    //連續執行cointiue N次,一般用於避免頻繁斷點
step N
next N

3.斷點
break 函式名        //設定斷在某個函式
break 檔名:行號 //設定斷在某一行
info break            //檢視設定的斷點資訊
break if condition //條件斷點  如果斷點已存在,可以用 condition N if i == 4 給斷點N加上條件
break 函式名 thread 執行緒號 //設定斷點只斷某個執行緒,通過info threads 檢視執行緒號
delete 斷點號 斷點號... //刪除一個或多個斷點
disable 斷點號 斷點號... //禁止一個或多個斷點
enable 斷點號 斷點號... //開啟一個或多個斷點
command 斷點號 //斷點觸發時,執行命令,一般用於列印變數
(gdb) command 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>print x
>end
(gdb)

4.檢測點
watch //為表示式(變數)expr設定一個觀察點。一量表達式值有變化時,馬上停住程式。
rwatch //當表示式(變數)expr被讀時,停住程式。
awatch //當表示式(變數)的值被讀或被寫時,停住程式。
info watchpoints //列出當前所設定了的所有觀察點。

經驗:觀察某個變數是否變化,被讀或者被寫,由於變數只在某一個作用域,可以獲取變數的地址,然後觀察。
比如:觀察examined_rows變數神馬時候被修改
(1).p &examined_rows,得到地址
(2).watch *(ha_rows *) 0x7ffec8005e28,則可以觀察這個變數的變化情況。

5.檢視變數
(1)設定
set print elements N //指定列印的長度,對長字串特別有用。
set print element 0 //輸出完整的字串
set print pretty //設定GDB列印結構的時候,每行一個成員,並且有相應的縮排,預設是關閉的
print {type} variable 
比如:
(gdb) p {ABC} 0x7fffffffe710
$2 = {val = 1.5, val2 = 10}

print xxx //列印變數
p /x xxx //16進位制顯示
p [email protected]_len //列印字串

info locals //打印出當前函式中所有區域性變數及其值。
info args //打印出當前函式的引數名及其值。
display 變數 //自動列印變數
undisplay //取消自動列印
注意:預設編譯的時候,除錯過程是看不見巨集的值的,編譯時候需要給選項。-g3

6.記憶體檢視
格式: x /nfu <addr> x 是 examine 的縮寫 
a.n表示要顯示的記憶體單元的個數 
b.f表示顯示方式, 可取如下值
(1).x 按十六進位制格式顯示變數。
(2).d 按十進位制格式顯示變數。
(3).u 按十進位制格式顯示無符號整型。
(4).o 按八進位制格式顯示變數。
(5).t 按二進位制格式顯示變數。
(6).a 按十六進位制格式顯示變數。
(7).i 指令地址格式
(8).c 按字元格式顯示變數。
(9).f 按浮點數格式顯示變數。
c.u表示一個地址單元的長度
(1).b表示單位元組,
(2).h表示雙位元組,
(3).w表示四位元組,
(4).g表示八位元組

比如:x/3xh buf 
表示從記憶體地址buf讀取內容,3表示三個單位,x表示按十六進位制顯示,h表示以雙位元組為一個單位。

7.多執行緒除錯
info threads //檢視執行緒
thread thread_no //切換到執行緒號
thread apply all command //所有執行緒都執行命令列印棧楨
比如:thread apply all bt //所有執行緒都列印棧楨

(1)執行緒鎖
show scheduler-locking 
set scheduler-locking on
set scheduler-locking off
預設是off,當程式繼續執行的時候如果有斷點,那麼就把所有的執行緒都停下來,直到你指定某個執行緒繼續執行(thread thread_no apply continue).
但是如果直接在當前執行緒執行continue的話,預設是會啟動所有執行緒。這種模式有一種副作用,如果多個執行緒都斷在同一個函式,這時候除錯會出問題。
這個時候需要開啟執行緒鎖,但開啟執行緒鎖,意味著其它執行緒不能運行了。

(2)non-stop模式(7.0以後的版本支援)
set target-async 1
set pagination off
set non-stop on
gdb啟動了不停模式,除了斷點有關的執行緒會被停下來,其他執行緒會執行。

8.訊號量
(1).singal 傳送訊號
假定你的程式已將一個專用的 SIGINT(鍵盤輸入,或CTRL-C;訊號2)訊號處理程式設定成採取某個清理動作,
要想測試該訊號處理程式,你可以設定一個斷點並使用如下命令:
(gdb) signal 2
(2).handle 攔截訊號
Handle命令可控制訊號的處理,他有兩個引數,一個是訊號名,另一個是接受到訊號時該作什麼。幾種可能的引數是:
* nostop 接收到訊號時,不要將它傳送給程式,也不要停止程式。
* stop 接受到訊號時停止程式的執行,從而允許程式除錯;顯示一條表示已接受到訊號的訊息(禁止使用訊息除外)
* print 接受到訊號時顯示一條訊息
* noprint 接受到訊號時不要顯示訊息(而且隱含著不停止程式執行)
* pass 將訊號傳送給程式,從而允許你的程式去處理它、停止執行或採取別的動作。
* nopass 停止程式執行,但不要將訊號傳送給程式。 
比如:
handle SIGPIPE stop print //截獲SIGPIPE訊號,程式停止並列印資訊
handle SIGUSR1 nostop noprint //忽略SIGUSR1訊號

9.生產環境使用GDB場景
核心轉儲(coredump)
(1).配置產生core檔案
前置條件:確保系統配置的core file size足夠,一般設定成unlimited
ulimit -c unlimited

配置corefile的引數:
echo 2 > /proc/sys/fs/suid_dumpable [程式中切換使用者,也要產生corefile]
mkdir /tmp/corefiles 
chmod 777 /tmp/corefiles
echo "/tmp/corefiles/core">/proc/sys/kernel/core_pattern //配置core檔案產生的目錄為/tmp/corefiles
echo "1" > /proc/sys/kernel/core_uses_pid

kill -sigsegv pid  //模擬異常記憶體訪問訊號

注意:
a.確保配置的目錄有足夠的磁碟空間,否則產生core檔案可能不完整。
b.對於mysqld而言,要保證正確產生core-file,需要加上--core-file,預設這個引數是不開啟的。
c.kill -9 pid 是不能產生core檔案的,因為SIGKILL訊號不能被捕獲。

(2).使用core檔案
gdb /usr/mysql/bin/mysqld core.24556

(3).dump已經執行程序的狀態資訊
gdb attach pid
(gdb) generate-core-file
除錯完畢後,通過detach命令退出。
另外,通過gcore pid 命令也可以dump core檔案,生成在當前目錄下。

(4).列印執行緒資訊
pstack pid
pt-pmp -p pid
pstack和pt-pmp都可以列印執行緒的資訊,但是pt-pmp會對同類堆疊的執行緒做聚合彙總,相對於pstack功能更強大,顯示也更友好。

(5).altert日誌
這裡主要針對mysqld問題排查,mysqld異常crash後,有時候在alter日誌中可以看到最後crash執行緒的堆疊,但是一般只有函式名或一串二進位制地址,無法定位到具體是crash到哪一行,通過addr2line可以解這個問題。
比如:alter日誌中記錄crash時的地址是0x64bd60,通過如下命令,可以定位到具體是哪一行
addr2line -e /usr/mysql/bin/mysqld 0x64bd60
/home/admin/131_20160715135613566_11155487_code/rpm_workspace/sql/sql_parse.cc:3067