天天看點

GDB調試

多線程調試可能是問得最多的。其實,重要就是下面幾個指令:

info thread 檢視目前程序的線程。

thread <id> 切換調試的線程為指定id的線程。

break file.c:100 thread all 在file.c檔案第100行處為所有經過這裡的線程設定斷點。

set scheduler-locking off|on|step,這個是問得最多的。在使用step或者continue指令調試目前被調試線程的時候,其他線程也是同時執行的,怎麼隻讓被調試程式執行呢?通過這個指令就可以實作這個需求。

off 不鎖定任何線程,也就是所有線程都執行,這是預設值。

on 隻有目前被調試程式會執行。

step 在單步的時候,除了next過一個函數的情況(熟悉情況的人可能知道,這其實是一個設定斷點然後continue的行為)以外,隻有目前線程會執行。

這個問題超多。在gdb下,我們無法print宏定義,因為宏是預編譯的。但是我們還是有辦法來調試宏,這個需要gcc的配合。

在gcc編譯程式的時候,加上-ggdb3參數,這樣,你就可以調試宏了。

另外,你可以使用下述的gdb的宏調試指令 來檢視相關的宏。

info macro – 你可以檢視這個宏在哪些檔案裡被引用了,以及宏定義是什麼樣的。

macro – 你可以檢視宏展開的樣子。

這個問題問的也是很多的,太多的朋友都說找不到源檔案。在這裡我想提醒大家做下面的檢查:

編譯程式員是否加上了-g參數以包含debug資訊。

路徑是否設定正确了。使用gdb的directory指令來設定源檔案的目錄。

下面給一個調試/bin/ls的示例(ubuntu下)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

<code>$ apt-get</code><code>source</code><code>coreutils</code>

<code>$</code><code>sudo</code><code>apt-get</code><code>install</code><code>coreutils-dbgsym</code>

<code>$ gdb</code><code>/bin/ls</code>

<code>gnu gdb (gdb) 7.1-ubuntu</code>

<code>(gdb) list main</code>

<code>1192</code><code>ls</code><code>.c: no such</code><code>file</code><code>or directory.</code>

<code>in</code><code>ls</code><code>.c</code>

<code>(gdb) directory ~</code><code>/src/coreutils-7</code><code>.4</code><code>/src/</code>

<code>source directories searched:</code><code>/home/hchen/src/coreutils-7</code><code>.4:$cdir:$cwd</code>

<code>1192 }</code>

<code>1193 }</code>

<code>1194</code>

<code>1195 int</code>

<code>1196 main (int argc, char **argv)</code>

<code>1197 {</code>

<code>1198 int i;</code>

<code>1199 struct pending *thispend;</code>

<code>1200 int n_files;</code>

<code>1201</code>

條件斷點是文法是:break [where] if [condition],這種斷點真是非常管用。尤其是在一個循環或遞歸中,或是要監視某個變量。注意,這個設定是在gdb中的,隻不過每經過那個斷點時gdb會幫你檢查一下條件是否滿足。

有時候,我們需要調試的程式需要有指令行參數,很多朋友都不知道怎麼設定調試的程式的指令行參數。其實,有兩種方法:

gdb指令行的 –args 參數

gdb環境中 set args指令。

有時候,在調試程式時,我們不單單隻是檢視運作時的變量,我們還可以直接設定程式中的變量,以模拟一些很難在測試中出現的情況,比較一些出錯,或是switch的分支語句。使用set指令可以修改程式中的變量。

另外,你知道gdb中也可以有變量嗎?就像shell一樣,gdb中的變量以$開頭,比如你想列印一個數組中的個個元素,你可以這樣:

<code>(gdb)</code><code>set</code><code>$i = 0</code>

<code>(gdb) p a[$i++]</code>

<code>...</code><code>#然後就一路回車下去了</code>

當然,這裡隻是給一個示例,表示程式的變量和gdb的變量是可以互動的。

也許,你很喜歡用p指令。是以,當你不知道變量名的時候,你可能會手足無措,因為p指令總是需要一個變量名的。x指令是用來檢視記憶體的,在gdb中 “help x” 你可以檢視其幫助。

x/x 以十六進制輸出

x/d 以十進制輸出

x/c 以單字元輸出

x/i 反彙編 – 通常,我們會使用 <code>x/10i $ip-20 來檢視目前的彙編($ip是指令寄存器)</code>

x/s 以字元串輸出

有一些朋友問我如何自動化調試。這裡向大家介紹command指令,簡單的了解一下,其就是把一組gdb的指令打包,有點像字處理軟體的“宏”。下面是一個示例:

<code>(gdb)</code><code>break</code><code>func</code>

<code>breakpoint 1 at 0x3475678:</code><code>file</code><code>test</code><code>.c, line 12.</code>

<code>(gdb)</code><code>command</code><code>1</code>

<code>type commands</code><code>for</code><code>when breakpoint 1 is hit, one per line.</code>

<code>end with a line saying just</code><code>"end"</code><code>.</code>

<code>&gt;print arg1</code>

<code>&gt;print arg2</code>

<code>&gt;print arg3</code>

<code>&gt;end</code>

<code>(gdb)</code>

當我們的斷點到達時,自動執行command中的三個指令,把func的三個參數值打出來。