GDB 的 七個(gè)單步調(diào)試命令
調(diào)試器 是一個(gè)可以運(yùn)行你的代碼并檢查問(wèn)題的軟件。??GNU Debugger???(GBD)是最流行的調(diào)試器之一,在這篇文章中,我研究了 GDB 的 ??step?
?? 命令和其他幾種常見情況的相關(guān)命令。??step?
? 是一個(gè)被廣泛使用的命令,但它有一些人們不太了解的地方,可能會(huì)使得他們十分困惑。此外,還有一些方法可以在不使用 ??step?
?? 命令的情況下進(jìn)入一個(gè)函數(shù),比如使用不太知名的 ??advance?
? 命令。
1、無(wú)調(diào)試符號(hào)
考慮以下這個(gè)簡(jiǎn)單的示例程序:
如果你在沒有 調(diào)試符號(hào)debugging sysbols 的情況下進(jìn)行編譯(LCTT 譯注:即在使用 ??gcc?
? 編譯程序時(shí)沒有寫 ??-g?
? 選項(xiàng)),然后在 ??bar?
? 上設(shè)置一個(gè)斷點(diǎn),然后嘗試在這個(gè)函數(shù)內(nèi)使用 ??step?
? 來(lái)單步執(zhí)行語(yǔ)句。GDB 會(huì)給出一個(gè) 沒有行號(hào)信息no line number information
2、stepi 命令
但是你仍然可以在沒有行號(hào)信息的函數(shù)內(nèi)部單步執(zhí)行語(yǔ)句,但要使用 ??stepi?
? 命令來(lái)代替 ??step?
?。??stepi?
? 一次只執(zhí)行一條指令。當(dāng)使用 GDB 的 ??stepi?
? 命令時(shí),先做 ??display/i $pc?
? 通常很有用,這會(huì)在每一步之后顯示 程序計(jì)數(shù)器program counter 的值和相應(yīng)的 機(jī)器指令machine instruction:
在上述的 ??display?
? 命令中,??i?
? 代表機(jī)器指令,??$pc?
? 表示程序計(jì)數(shù)器寄存器(即 PC 寄存器)。
使用 ??info registers?
? 命令,來(lái)打印寄存器的內(nèi)容,也是十分有用的。
3、復(fù)雜的函數(shù)調(diào)用
在帶調(diào)試符號(hào)的 ??-g?
? 選項(xiàng),重新編譯示例程序后,你可以使用行號(hào)在 ??main?
? 中 ??bar?
? 調(diào)用上設(shè)置斷點(diǎn),然后再單步執(zhí)行 ??bar?
? 函數(shù)的語(yǔ)句:
接下來(lái),用 ??step?
?,來(lái)單步執(zhí)行 ??bar()?
? 函數(shù)的語(yǔ)句:
函數(shù)調(diào)用的參數(shù)需要在實(shí)際的函數(shù)調(diào)用之前進(jìn)行處理,??bar()?
? 函數(shù)的參數(shù)是 ??num()?
? 函數(shù),所以 ??num()?
? 會(huì)在 ??bar()?
? 被調(diào)用之前執(zhí)行。但是,通過(guò) GDB 調(diào)試,你怎么才能如愿以償?shù)剡M(jìn)入 ??bar()?
? 函數(shù)呢?你可以使用 ??finish?
? 命令,并再次使用 ??step?
? 命令。
4、tbreak 命令
??tbreak?
? 命令會(huì)設(shè)置一個(gè)臨時(shí)斷點(diǎn)。如果你不想設(shè)置永久斷點(diǎn),那么這個(gè)命令是很有用的。舉個(gè)例子??,你想進(jìn)入一個(gè)復(fù)雜的函數(shù)調(diào)用,例如 ??f(g(h()), i(j()), ...)?
?,在這種情況下,你需要一個(gè)很長(zhǎng)的 ??step/finish/step?
? 序列,才能到達(dá) ??f?
? 函數(shù)。如果你設(shè)置一個(gè)臨時(shí)斷點(diǎn),然后再使用 ??continue?
? 命令,這樣就不需要以上的序列了。為了證明這一點(diǎn),你需要像以前一樣將斷點(diǎn)設(shè)置在 ??main?
? 的 ??bar?
? 調(diào)用上。然后在 ??bar?
? 上設(shè)置臨時(shí)斷點(diǎn)。當(dāng)?shù)竭_(dá)該臨時(shí)斷點(diǎn)后,臨時(shí)斷點(diǎn)會(huì)被自動(dòng)刪除。
在調(diào)用 ??bar?
? 的時(shí)候遇到斷點(diǎn),并在 ??bar?
? 上設(shè)置臨時(shí)斷點(diǎn)后,你只需要使用 ??continue?
? 繼續(xù)運(yùn)行直到 ??bar?
? 結(jié)束。
5、disable 命令
類似地,你也可以在 ??bar?
? 上設(shè)置一個(gè)正常的斷點(diǎn),然后執(zhí)行 ??continue?
?,然后在不再需要第二個(gè)斷點(diǎn)時(shí),使用 ??disable?
? 命令禁用這個(gè)斷點(diǎn),這樣也能達(dá)到與 ??tbreak?
? 相同的效果。
正如你所看到的,??info breakpoints?
? 命令在 ??Enb?
? 列下顯示為 ??n?
?,這意味著這個(gè)斷點(diǎn)已被禁用。但你也能在再次需要這個(gè)斷點(diǎn)時(shí),再啟用它。
6、advance 命令運(yùn)行程序到指定的位置
另一個(gè)進(jìn)入函數(shù)內(nèi)部的方法是 ??advance?
? 命令。你可以簡(jiǎn)單地用 ??advance bar?
?,來(lái)代替 ??tbreak bar ; continue?
?。這一命令會(huì)將程序繼續(xù)運(yùn)行到指定的位置。
??advance?
? 命令的一個(gè)很棒的地方在于:如果程序并沒有到達(dá)你試圖進(jìn)入的位置,那么 GDB 將在當(dāng)前函數(shù)運(yùn)行完成后停止。因此,程序的執(zhí)行會(huì)受到限制:
7、skip 命令
進(jìn)入 ??bar?
? 函數(shù)的另一種方式是使用 ??skip num?
? 命令:
請(qǐng)使用 ??info skip?
? 命令,來(lái)了解 GDB 跳過(guò)了哪些函數(shù)。??num()?
? 函數(shù)被標(biāo)記為 ??y?
?,表示跳過(guò)了 ??num()?
? 函數(shù):
如果不再需要 ??skip?
?,可以禁用(并稍后重新啟用)或完全刪除它。你可以添加另一個(gè) ??skip?
?,并禁用第一個(gè) ??skip?
?,然后全部刪除。要禁用某個(gè) ??skip?
?,必須指定其編號(hào)(例如,??skip disable 1?
?),如果沒有指定,則會(huì)禁用所有的 ??skip?
?。啟用或刪除 ??skip?
? 的工作原理相同:
GDB 的 step 命令
使用 GDB 的 ??step?
? 命令是調(diào)試程序的一個(gè)有用工具。即使是復(fù)雜的函數(shù),也有幾種方法可以單步調(diào)試這些函數(shù),所以下次你在排除代碼問(wèn)題的時(shí)候,可以嘗試一下這些 GDB 技術(shù)。