每個程式設計師,無論經驗如何豐富,都無法完全避免軟體中出現bug的情況。因此,排查和修復bug成為軟體開發週期中至關重要的任務之一。雖然有許多方法可以用來排查bug,例如測試和程式碼自審,但專用偵錯器軟體也可以幫助準確地定位問題所在,以便進行修復。
對於那些使用C/C 程式語言或Fortran和Modula-2開發軟體的程式設計師來說,有一款優秀的調試工具——GDB,將會是他們的福音。 GDB不僅可以幫助程式設計師更輕鬆地偵錯程式碼中的bug和其他問題,而且還提供了許多有用的功能和選項。在本文中,我們將討論一些GDB偵錯器的基礎知識,以及它所提供的一些實用功能和選項。
在我們開始之前,值得一提的是,文章中的所有說明和範例都已經在 Ubuntu 14.04 LTS 中測試過。教程中的範例程式碼都是 C 語言寫的;使用的 shell 為 bash(4.3.11);GDB 版本為 7.7.1。
#通俗的講,GDB 可以讓你看到程式在執行過程時的內部流程,並幫你明確問題的所在。我們將在下一節透過一個有效的範例來討論 GDB 偵錯器的用法,但在此之前,我們先來探討一些之後對你有幫助的基本要點。
首先,為了能夠順利使用類似 GDB 這樣的偵錯器,你必須以指定的方式編譯程序,讓編譯器產生偵錯器所需的偵錯資訊。例如,在使用 gcc 編譯器(我們將在本教學之後的章節用它來編譯 C 程式範例)編譯程式碼的時候,你需要使用-g 命令列選項。
想要了解 gcc 編譯器手冊頁中關於 -g 命令列選項相關的內容,請看這裡。
下一步,確保在你的系統中已經安裝 GDB 偵錯器。如果沒有安裝,而且你使用的是基於 Debian 的系統(如 Ubuntu),那麼你就可以使用以下命令輕鬆安裝該工具:
sudo apt-get install gdb
在其他發行版上的安裝方法,請看這裡。
現在,當你按照上述的方式編譯完程式(gcc -g 命令列選項),同時也已經安裝好 GDB 調試器,那麼你就可以使用以下命令讓程式在調試模式中運行:
gdb [可执行程序的名称]
這樣做會初始化 GDB 偵錯器,但你的執行程式此時還不會被啟動。在這個時候你就可以定義調試相關的設定。例如,你可以在特定行或函數中設定一個斷點讓 GDB 在該行暫停程式的執行。
接著,為了啟動你的程序,你必須輸入執行以下 gdb 指令:
run
在這裡,值得一提的是,如果你的程式需要一些命令列參數,那麼你可以在這裡指定這些參數。例如:
run [参数]
GDB 提供了許多有用的指令,在調試的時候總是能派的上用場。我們將在下一節討論其中一部分命令。
#現在我們對 GDB 及其用法有了基本的概念。因此,讓我們舉例來應用所學的知識。這是一段範例程式碼:
#include int main() { int out = 0, tot = 0, cnt = 0; int val[] = {5, 54, 76, 91, 35, 27, 45, 15, 99, 0}; while(cnt printf("/n Total = [%d]/n", tot); return 0; }
簡單說明一下這段程式碼要做什麼事。取得 val數組中每一個值,將其賦值給out 變量,然後將tot 之前的值與0xffffffff/out 的結果值累加,並賦值給 tot 變數。
這裡遇到的問題是,當執行這段程式碼編譯後的可執行程式時,產生以下錯誤:
$ ./gdb-testFloating point exception (core dumped)
因此,要偵錯這段程式碼,第一步是使用 -g
選項編譯程式。命令如下:
gcc -g -Wall gdb-test.c -o gdb-test
接著,讓我們執行 GDB 偵錯器並指定要偵錯的可執行程式。命令如下:
gdb ./gdb-test
現在,我剛剛得到的錯誤是 Floating point exception,大部分人可能已經知道,這是因為 n % x,當 x 為 0 時導致的錯誤。所以,考慮到這一點,我在 11 行程式碼除法運算的位置處新增了一個斷點。如下:
(gdb)&;break 11
注意 (gdb) 是偵錯器的提示訊息,我只輸入了break 11 指令。
現在,讓 GDB 開始執行程式:
run
當斷點第一次被命中時,GDB 顯示如下輸出:
Breakpoint 1, main () at gdb-test.c:11 11 tot = tot + 0xffffffff/out; (gdb)
正如你所看到的那樣,偵錯器會顯示斷點所在的行程式碼。現在,讓我們列印出此時out 的值。如下:
(gdb) print out $1 = 5 (gdb)
如上所示,值 5被打印出来了。这个时候一切都还是正常的。让调试器继续执行程序直到命中下一个断点,可以通过使用 c 命令来完成:
c
重复上述操作,直到 out值变为0 时。
... ... ... Breakpoint 1, main () at gdb-test.c:11 11 tot = tot + 0xffffffff/out; (gdb) print out $2 = 99 (gdb) c Continuing. Breakpoint 1, main () at gdb-test.c:11 11 tot = tot + 0xffffffff/out; (gdb) print out $3 = 0 (gdb)
现在,为了进一步确认问题,我使用 GDB 的s (或 step) 命令代替 c 命令。因为,我只想让当前程序在第 11 行之后暂停,再一步步执行,看看这个时候是否会发生崩溃。
以下是执行之后输出信息:
(gdb) s Program received signal SIGFPE, Arithmetic exception. 0x080484aa in main () at gdb-test.c:11 11 tot = tot + 0xffffffff/out;
是的,如上输出的第一行内容所示,这就是抛出异常的地方。当我再次尝试运行s 命令时,问题最终也得到了确认:
(gdb) s Program terminated with signal SIGFPE, Arithmetic exception. The program no longer exists.
通过这种方式,你就可以使用 GDB 调试你的程序。
GDB 提供了很多功能供用户研究和使用,在这里,我们仅仅只介绍了很少一部分内容。通过 GDB 的手册页可以进一步了解这个工具,当你在调试代码的时候,尝试使用一下它。GDB 调试器有一定的学习难度,但是它很值得你下功夫学习。
以上是在 Linux 中調試 C 程式的福音-gdb的詳細內容。更多資訊請關注PHP中文網其他相關文章!