GDB調試器使用總結


概述:GDB是linux下調試程序的神器,做為linux程序員,如果不能熟練的使用GDB進行程序調試,那將是很失敗的事情。強大的功能使GDB的使用也變得比較復雜,如果是初學者肯定會比繁雜的命令嚇到。下面是整理的一些我認為會比較有幫助的部分。下文中以">"開頭的命令是linux的shell命令,以"(GDB)"開頭的則是GDB內部命令。
 

0.轉儲功能(core dump):

     (1).開啟轉儲功能:首先用 >ulimit -c 查看是否開啟轉儲功能,如果命令返回不是0則已經開啟,否則就是未開啟。>ulimit -c unlimited 命令可以開啟轉儲功能。也可以用 >ulimit -c 1024來設定轉儲文件的大小。
 
     (2).設定轉儲文件生成地址:編輯/etc/sysctl.conf文件,在文件最后加入下列兩行:
        kernel.core_pattern = /var/core/%t-%e-%p.core
        kernel.core_uses_pid = 0
    然后將文件保存起來,保存完成之后執行:>sysctl -p命令(注意:執行這個命令需要root權限。)。此時執行一個會當機的程序,會在/var/core/文件夾下面生成轉儲文件(例如:1432378356-a.out-4821.core)。上面設定的文件名是有固定格式的,core_pattern中設定的就是文件保存目錄和文件的名字格式。其中%t是轉儲時的unix時間戳,%e是當前執行的文件名,%p是crash進程的PID。格式符說明如下:
格式符號
說明
%%
%字符本身
%p
被轉儲進程的進程ID(PID)
%u
被轉儲進程的真是用戶ID(UID)
%g
被轉儲進程的真是組(GID)
%s
引發轉儲的信號編號
%t
轉儲時間,unix時間戳(從1970年1月1日0時開始的秒數)
%h
主機名
%e
可執行文件的名稱
%c
轉儲文件的大小上限(內核版本2.6.24以后可使用)
     (3).轉儲文件的壓縮:通過在/etc/sysctl.conf文件的core_pattern中加入壓縮腳本以及管道命令,可以對生成的轉儲文件進行壓縮。首先在/etc/sysctl.conf文件中加入下列兩行(如果已經存在則修改成下面的形式):
        kernel.core_pattern = |/usr/localsbin/zipsh %t %e %p
        kernel.core_uses_pid = 0
    保存文件,然后執行:>sysctl -p命令。
    /usr/local/sbin/zipsh文件的內容如下:
        #!/bin/sh
        exec gzip - > /var/core/$1-$2-$3.core.gz
    這樣的話,以后都會在/var/core下生成壓縮的轉儲文件。

1.基本信息查看:
     (1).棧信息:不管是操作轉儲文件還是用GDB設置斷點進行調試,都可以輸入(GDB)bt打印棧內容進行查看。一般的當機BUG,看下當機的位置,然后看下源代碼基本就可以解決了。但是很多情況下簡單的(GDB)bt還查不到問題,這時候就要涉及到比較復雜的操作。下面羅列了一些對棧的操作:
        (GDB) bt:顯示所有棧幀。
        (GDB) bt 10:顯示前面10個棧幀。
        (GDB) bt -10:顯示后面10個棧幀。
        (GDB) bt full:顯示棧幀以及局部變量。
        (GDB) bt full 10:顯示前面10個棧幀以及局部變量。
        (GDB) bt full -10:顯示后面10個棧幀以及局部變量。
        (GDB) frame <棧幀編號>:進入指定的棧幀中,然后可以查看當前棧幀中的局部變量,以及棧幀內容等信息。
        (GDB) info frame <棧幀編號>:可以查看指定棧幀的詳細信息。
        (GDB) up:進入上層棧幀。
        (GDB) down:進入下層棧幀。
 
     (2).變量:調試BUG過程中查看變量信息是很有幫助的操作,查看方式如下:
        (GDB) p <變量名>
 
     (3).寄存器:對於調試來說寄存器中的值也很重要,可以查看到當前正在執行的指令的地址等。具體操作羅列如下:   
        (GDB) info reg:顯示所有寄存器。可以簡寫為:i r。如果要查看具體的寄存器可以這樣:i $ebx
        (GDB) p $eax:顯示eax寄存器內容。
        (GDB) p/c $eax:用字符顯示eax寄存器內容,反斜杠后面的是顯示格式,可使用的格式見下表:該表在顯示內存內容的x命令中也是通用的。
格式
說明
x
顯示為十六進制數
d
顯示為十進制數
u
顯示為無符號十進制數
o
顯示為八進制數
t
顯示為二進制數
a
顯示為地址
c
顯示為字符(ASCII)
f
顯示為浮點小數
s
顯示為字符串
i
顯示為機器語言(僅在顯示內存的x命令中可用)
     (4).內存:可以查看具體內存地址中的內容,比如:目前執行的匯編指令,以及棧中內容等。
        (GDB) x $pc:顯示程序指針指向位置的內容。
        (GDB) x/i $pc:顯示程序當前位置的匯編指令。
        (GDB) x/10i $pc:顯示程序當前位置開始往后的10條匯編指令。
        (GDB) disassem $pc:反匯編當前函數。簡寫為:disas $pc。
   
2.調試:
     (1).斷點:調試程序中,設置斷點進行調試是最方便有效的手段,因此學會如果靈活設置斷點是調試的基本功。:
         A.設置斷點:
            (GDB) break <函數名>:對當前正在執行的文件中的指定函數設置斷點。可簡寫為:(GDB) b <函數名>
            (GDB) break <行號>:對當前正在執行的文件中的特定行設置斷點。可簡寫為:(GDB) b <行號>
            (GDB) break <文件名:行號>:對指定文件的指定行設置斷點。最常用的設置斷點方式。可簡寫為:(GDB) b <文件名:行號>
            (GDB) break <文件名:函數名>:對指定文件的指定函數設置斷點。C++類中的方法似乎不好使。可簡寫為:(GDB) b <文件名:函數名>
            (GDB) break <+/-偏移量>:當前指令行+/-偏移量出設置斷點。可簡寫為:b <+/-偏移量>
            (GDB) break <*地址>:指定地址處設置斷點。可簡寫為:b <*地址>
         B.查看、刪除斷點:            
            (GDB) info break :顯示所有斷點以及監視點。可簡寫為:(GDB) i b
            (GDB) delete <編號>:刪除編號指向的斷點或者監視點。可簡寫為:(GDB) d <編號>
            (GDB) clear <行號>:刪除改行的斷點。
            (GDB) clear <文件名:行號>:刪除改行的斷點。
         C.設置無效、有效斷點:
            (GDB) disable <斷點編號> : 當前斷點設置為無效。
            (GDB) enable <斷點編號>:當前斷點設置為有效。
            
     (2).監視點:可以監視某個變量,在變量被訪問或者被修改時程序會在當前點進入斷點。刪除,查看監視點的方式與斷點相同。設置監視點方式如下:            
        (GDB) watch <表達式>:表達式發生變化時暫停。
        (GDB) awatch <表達式>:表達式訪問或者改變時暫停。
        (GDB) rwatch <表達式>:表達式被訪問時暫停。
 
     (3).條件斷點:在調試程序過程中,有時候我們只想在某個條件下停止程序,然后進行單步調試,而條件斷點就是為此而設計。下面是條件斷點的操作方式:    
        (GDB) b <斷點> if <條件表達式> : 例如:b main.cpp:8 if x=10 && y=10
        (GDB) condition <斷點編號>:刪除該斷點的條件。
        (GDB) condition <斷點編號> <條件表達式>:修改斷點條件。例如:condition 1 x=10 && y=10
        
     (4).斷點命令:每次斷點發生時候,想要查看的變量很多時,如果每個變量都手動print則需要浪費很多時間。斷點命令可以在斷點發生時批量執行GDB命令。下面是斷點命令的設置方式:
        (GDB) commands <斷點編號>
        (GDB) >print x
        (GDB) >print y
        (GDB) >end
        首先輸入GDB命令commands <斷點編號>然后回車,這時候會出現>提示符。出現>提示符后可以輸入斷點發生時需要執行的GDB命令,每行一條,全部輸入完成后輸入end結束斷點命令。
        
     (5).反復執行:單步執行時如果進入了你不關心的函數,你想立即跳出函數;或者進入了大循環中,你想立即循環。下面的命令可以幫到你:    
        (GDB) ignore <斷點編號> <次數>:忽略N次斷點。
        (GDB) c N: 執行N次指令,會忽略斷點。
        (GDB) s/stepi/n/nexti N:往后執行N行,不會忽略斷點。
        (GDB) finish:執行完當前函數后停止,不會忽略斷點。
        (GDB) until:執行完當前循環后停止,不會忽略斷點。
        (GDB) until <地址>:執行到指定地址停止。
        
     (6).設置變量值:對變量的值進行控制,可以更快的調試自己的程序。下面就是設置變量值的方法:
         (GDB) set variable <變量> = <表達式>:將變量的值設定為指定表達式的值。例如 set variable x=10
 
     (7).手動生成轉儲文件:
        (GDB) generate-core-file 簡寫為:(GDB) gcore
 
3.調試在線進程:
     (1).啟動GDB時鏈接目標進程:在啟動GDB的時候,通過參數-p指定目標進程,就可以進入調試狀態。剛鏈接成功后,程序是暫停運行狀態,你可以進行設置斷點等操作,然后輸入(GDB) c 命令繼續運行。命令如下:
        >gdb -p <PID>:PID是進程ID,可以通過>ps aux | grep <程序名> 獲得。或者直接 >gdb -p  `pidof <程序名>`也可以。>pidof <程序名>是通過名字獲取進程ID的命令。
 
     (2).GDB中鏈接目標進程:
        (GDB) attach <PID>
 
     (3).斷開鏈接:
        (GDB) detach
 
4.調試多線程程序:
     (1).查看線程:
        (GDB) info thread:查看所有線程信息,可簡寫為:i thr
 
     (2).切換到指定線程:
         (GDB) thread <線程編號>:選中出現問題的線程,可簡寫為:thr <線程編號>
 
     (3).調試守護者進程:守護者進程在啟動好子進程后,會自動關閉主進程,如果沒有設定監控模式的話,GDB會提示斷開與進程的鏈接。所以必須設定監控對象,設置方式如下:
        (GDB) set follow-fork-mode child/parent

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM