2010年7月29日 星期四

[gdb 教學] 一個簡單的 gdb 使用範例

參考 這裡 
前言 : 
有鑑於我們常常需要再不同平台開發與進行測試, 在Windows 下有非常方便的GUI 工具如 Visual Studio可以幫我們進行Debug的工作, 但是在 Linux Console 下要追某個 bug 或異常可能就不是這麼直觀了, 因此我們需要借重 gdb 這個工具來 Trace 某個 bug 生成的原因. 有關 gdb 官方文檔可以參考 這裡 

一個簡單的gdb 使用範例 : 
現在我們將就由一個簡單的範例來介紹一些 gdb 常用到的指令與實際使用 gdb 會遇到的問題. 首先我們有個程序會將使用者從 Console 輸入的兩個整數進行相加後, 將結果顯示在Console, 其代碼如下 : 

- Sample1.c 代碼 :
  1. #include <stdio.h>
  2.   
  3. int add(int a,int b);  
  4.   
  5.   
  6. int main() {  
  7.         int a=0,b=0;  
  8.         printf("Please give a: ");  
  9.         scanf("%d", &a);  
  10.         printf("Please give b: ");  
  11.         scanf("%d", &b);  
  12.         int c = add(a,b);  
  13.         printf("Result a+b=%d\n", c);  
  14. }  
  15.   
  16. int add(int a, int b) {  
  17.         return a;  
  18. }  

- 編譯代碼 
接著我們使用 gcc 編譯代碼, 要注意的是因為接著要使用 gdb 進行 debug, 因此在編譯是要使用 -g 參數 : 
suse-11_2:~/gccprac/gdbprac # gcc -g -o sample1 sample1.c <編譯代碼> 
suse-11_2:~/gccprac/gdbprac # ./sample1 <執行程式> 
Please give a: 1 
Please give b: 2 
Result a+b=1  

- 使用 gdb 
接著我們將使用 gdb 進行 debug, 請執行下面命令 : 

suse-11_2:~/gccprac/gdbprac # gdb ./sample1 <進入 gdb console>
Reading symbols from /root/gccprac/gdbprac/sample1...done.
(gdb) list <接著我們可以使用 list 檢視代碼>
1 #include
2
3 int add(int a,int b);
...(省略)...

接著根據代碼, 我們發現函數 add 很可疑, 於是接著在執行 add 函數時下斷點 : 

(gdb) break add <在 add函數下斷點>
Breakpoint 1 at 0x8048503: file sample1.c, line 17.
(gdb) info break <檢查目前斷點設定>
Num Type Disp Enb Address What
1 breakpoint keep y 0x08048503 in add at sample1.c:17

接著就開始執行程式 : 

(gdb) r 
Starting program: /root/gccprac/gdbprac/sample1
...(省略)...
Please give a: 10 <輸入 a 的值, 按Enter 結束>
Please give b: 20 <輸入 b 的值, 按Enter 結束>

Breakpoint 1, add (a=10, b=20) at sample1.c:17
17 return a;
(gdb) print a <顯示變數 a 的值>
$1 = 10
(gdb) list 17 <檢視 17行附近的源代碼>
12 int c = add(a,b);
13 printf("Result a+b=%d\n", c);
14 }
15
16 int add(int a, int b) {
17 return a<應該是 a+b>
18 }
(gdb) continue <繼續跑完程序>
Continuing.
Result a+b=10

Program exited with code 016.
(gdb) quit <離開gdb Console>

可以發現 函式 a 計算式錯誤, 請將 "return a;" 改成 "return a+b;" 後重新編譯後再使用gdb : 

(gdb) list 10
...(省略)...
11 scanf("%d", &b);
12 int c = add(a,b);
13 printf("Result a+b=%d\n", c);
14 }
(gdb) break 12 <在代碼12 行處下斷點>
Breakpoint 1 at 0x80484d1: file sample1.c, line 12.
(gdb) r
Starting program: /root/gccprac/gdbprac/sample1
Please give a: 10 <輸入 a 的值, 按Enter 結束>
Please give b: 20 <輸入 b 的值, 按Enter 結束>

Breakpoint 1, main () at sample1.c:12
12 int c = add(a,b);
(gdb) step <進入 add 函數, 如果使用 next, 則不會進入add 函數>
add (a=10, b=20) at sample1.c:17
17 return a+b;
(gdb) print a+b <檢視 a+b 的值>
$1 = 30
(gdb) next <執行下一行>
18 }
(gdb) next <執行下一行>
main () at sample1.c:13
13 printf("Result a+b=%d\n", c);
(gdb) display c <在執行每一行後都顯示 c 的值>
1: c = 30
(gdb) next <執行下一行>
Result a+b=30 
14 }
1: c = 30 
(gdb) c
Continuing.

Program exited with code 016.
(gdb) quit

補充說明 :
Linux 除錯利器 - GDB 簡介
Debugging with GDB (入門篇) 

Debug 是大家常常用到的東西.不管是自己寫程式也好,還是想改改別人寫好的東西, 又或者幫人家捉捉虫.總之呢,絕對是個常常用的到的東西.Dos, windows 底下,通常大家都在 用 softice. 這裡我就不介紹了,因為在前面的 "學習程式"中的"Assembly"裡面已經有了很詳 細的介紹了.這裡我來說說 linux 底下的 GDB 吧...

GDB 常用參數
如何設定 GDB Breakpoint :

Breakpoints are set with the break command (abbreviated b). The debugger convenience variable `$bpnum' records the number of the breakpoints you've set most recently; see section Convenience variables, for a discussion of what you can do with convenience variables.

4 則留言:

  1. 雖然現在才發現,但是閣下的Visual Studio好像拼錯了喔

    回覆刪除
    回覆
    1. 感謝提醒, 已更正!

      刪除
    2. 又發現一個小錯誤了...您C語言那部份的#include沒打完唷

      刪除
    3. 感謝提醒, 因為 '<' 與 '>' 是 HTML escape 字元, 所以貼上去會消失. 以更正.

      刪除

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...