一起talk GDB吧(第七回:GDB監視功能)
各位看官們,大家好,上一回中我們說的是GDB修改程式執行環境的功能,並且說了如何使用GDB修改變數
的值。這一回中,我們繼續介紹GDB的除錯功能:監視功能。當然了,我們也會介紹如何使用GDB的監視功
能。閒話休提,言歸正轉。讓我們一起talk GDB吧!
我們說的監視類似像電影中描述的哪種監視,只不過電影中的被監視物件通常是一些犯罪嫌疑人,而我們
的監視物件是執行著的程式,更具體點說,是程式中的儲存單元地址。GDB提供了監視功能,首先設定一個
監視點,GDB會自動監視該監視點上的變化了,如果監視點發生了變化,GDB就會在監視點哪裡停下來,這
時候,我們就能看到是誰讓監視點發生了變化。我來總結一下具體的步驟:
1.設定一個監視點。例子:watch giVal 該例子表示在giVal所在的儲存單元哪裡設定一個監視點。
2.先使用start命令開始除錯,當有程式修改監視點的儲存單元時它就會停下來。
3.使用c命令會再次執行程式,直到有程式操作觀察點監視的儲存單元時再次停下來。
光說不練,不是我們的風格,接下來,我們用具體的例子來說明如何使用監視功能。
#include<stdio.h> int g; void fun() { g = 3; } int main() { int a,b; a = 3; b = 5; g = a+b; printf("a+b = %d \n",g); fun(); printf("a+b = %d \n",g); return 0; }
1.編寫程式。開啟VIM,輸入上面的程式,並且儲存到m.c檔案中
2.編譯程式。在終端中輸入:gcc -g m.c -o s
3.執行程式。在終端中輸入:./s ,得到以下執行結果:
./s
a+b = 8
a+b = 3
大家可以看到程式中a=3,b=5,a+b=8這是小學生也會的數字呀,可是程式第一次輸出運算結果時還正確,
第二次輸出運算結果時就不正確了,這是怎麼回事?看官莫急,我們使用GDB的監視功能來除錯一下,很
快就能知道。誰修改了這個全域性變數。
在終端中輸入:gdb s //使用GDB除錯程式
(gdb) watch g
//設定一個監視點,監視全域性變數g
Hardware watchpoint 1: g
(gdb) start //開始除錯
Temporary breakpoint 2 at 0x8048435: file m.c, line 13.
Starting program: xxx/s
Temporary breakpoint 2, main () at m.c:13
13 a = 3;
(gdb) c //繼續除錯程式,直到監視點g發生變化
Continuing.
Hardware watchpoint 1: g
Old value = 0 //這裡顯示監視點發生了變化,並且列出了變化前後的值
New value = 8 //這時的運算結果是正確的
main () at m.c:17
17 printf("a+b = %d \n",g);
(gdb) c //運算結果正確,繼續除錯程式,直到監視點g發生變化
Continuing.
a+b = 8
Hardware watchpoint 1: g
Old value = 8 //這裡顯示監視點發生了變化,並且列出了變化前後的值
New value = 3 //g的值從8變成了3
fun () at m.c:8 //提示程式中第8行
8 }
(gdb) list 8 //觀看程式中第8行的內容
3 int g;
4
5 void fun()
6 {
7 g = 3; //大家看到了吧,原來是fun函式修改了g的值。
8 }
9
10 int main()
11 {
12 int a,b;
(gdb) stop //結束除錯
我們通過這個例子說明了如何在除錯過程中使用監視功能來除錯程式,並且找出了發生錯誤的原因。不過
該例子比較簡單,我們仔細觀察一下程式就能發現是fun函式修改了運算結果。在實際的程式中,就不會
像例子中這麼簡單了,希望看官們能夠舉一反三,靈活使用監視功能除錯程式。
監視功能也是GDB中一個十分強大的功能,在除錯全域性變數被修改,或者陣列越界錯誤非常有用。會C語言
的看官們都知道,全域性變數是C程式中一個十分讓人頭疼的東西,在有些程式中甚至不允許使用全域性變數,
使用GDB的監視功能可以監視全域性變數的一舉一動,只要全域性變數發生了變化,它就會停止下來。因此可
以把監視功能看作是全域性變數的剋星。
看官們,關於GDB的內容,今天咱們就說到這裡。欲知後事如何,且聽下回分解!