Linux中有一個強大的調試工具GDB(GNU Debugger),可以調試C和C++程式。 GDB的主要功能如下: 使用GDB的前提是,在編譯程式的時候需要加入-g選項,即 gcc -g xxx.c。當設置這個選項的時候,GCC會向程式中加入“楔子”,GDB能夠利用這些楔子與程式交互。 書上的測試 ...
Linux中有一個強大的調試工具GDB(GNU Debugger),可以調試C和C++程式。
GDB的主要功能如下:
- 設置斷點
- 顯示變數的值
- 單步執行
- 運行時修改變數的值
- 路徑跟蹤,方便跟蹤代碼
- 線程切換
- 其他的。。。
使用GDB的前提是,在編譯程式的時候需要加入-g選項,即 gcc -g xxx.c。當設置這個選項的時候,GCC會向程式中加入“楔子”,GDB能夠利用這些楔子與程式交互。
書上的測試程式一則:
/*文件名:ex02-gdb-01.c*/ #include <stdio.h> /* 用於printf*/ #include <stdlib.h> /*用於malloc*/ /* 聲明函數sum為static int類型 */ static int sum(int value); /* 用於控制輸入輸出的結構 */ struct inout { int value; int result; }; int main(int argc, char * argv[]) { /*申請記憶體*/ struct inout * io = (struct inout * ) malloc(sizeof(struct inout)); /*判斷是否成功*/ if (NULL == io) { /*失敗返回*/ printf("申請記憶體失敗\n"); return -1; } /*判斷輸入參數是否正確*/ if (argc != 2) { printf("參數輸入錯誤!\n"); return -1; } /* 獲得輸入的參數 */ io -> value = *argv[1] - '0'; /* 對value進行累加求和 */ io -> result = sum(io -> value); printf("你輸入的值為:%d,計算結果為:%d\n", io -> value, io -> result); return 0; } /* 累加求和函數 */ static int sum(int value) { int result = 0; int i = 0; /* 迴圈計算累加值 */ for (i = 0; i < value; i++) result += (i + 1); /*返回結果*/ return result; }
輸入gcc -o test gdb-01.c -g,使其加入“楔子”。下麵進入調試:
其中test是可執行文件的名字。
GDB常用的命令( 命令(命令簡寫):格式及含義 ):
file:載入(可執行)文件,使用在gdb命令後沒有接文件名的時候。
(gdb) file gdb-01.c "/home/tyruschin/ClionProjects/gdb_learning/gdb-01.c": not in executable format: 不可識別的文件格式 (gdb) file test Load new symbol table from "test"? (y or n) y Reading symbols from test...done.
set args:設置輸入參數(可以在run命令中設置,如果不設置的話,run的時候預設使用前一條run命令的參數),set args 參數1 參數2 ...
(gdb) set args 2 (gdb) run Starting program: /home/tyruschin/ClionProjects/gdb_learning/test 2 你輸入的值為:2,計算結果為:3
show:顯示變數,show args
(gdb) set args 2 3 (gdb) show args Argument list to give program being debugged when it is started is "2 3".
list(l):表示列出文件的代碼內容。list 1表示從第一行開始,預設顯示10行,按下回車鍵可以繼續列印10行;list 1,4表示顯示1到4行,此時再次按下回車則繼續列印下麵的10行。
break(b):設置斷點,b 行號或函數名。程式運行到斷點的位置會終端,等待用戶的下一步操作指令。
具體的使用(如果有多個文件共同生成一個目標執行文件的時候,要指定文件名,如 b gdb-01.c:38 ):
- break 行號:程式停止在設定的行之前
- break 函數名稱:程式停止在設定的函數之前
- break 行數或者函數if條件:條件為真的情況下,到達指定行或函數時停止
查看斷點信息,info break
// 沒有寫編號就表示全部編號了
刪除指定的某個斷點:delete breakpoints 斷點編號(在info break 中找到)
禁止斷點:disable b 斷點編號(此時info break中的Enb列中,顯示的是n而不是y)
允許斷點(禁止的反操作):enable b 斷點編號
清除斷點:clear 斷點行號
run(r):運行程式,run args,這裡的args和set args中的是一致的。運行到遇到斷點會暫停下來。
(gdb) run 3 Starting program: /home/tyruschin/ClionProjects/gdb_learning/test 3 Breakpoint 1, sum (value=3) at gdb-01.c:39 39 int result = 0;
print(p):列印變數內容,功能強大,可以列印任何有效表達式的值。
設置斷點在28行,以上是p列印變數的例子,其中io是一個結構體數組,argv是一個字元串數組,@後面的數字表示列印的個數,超過個數之後列印處的結果是隨機的。。
whatis:變數類型檢測,列印數組或者變數的類型,whatis 變數名
ptype:變數類型檢測,結構的詳細定義
set:修改變數的值,set xx=val
display:display 變數,每次在調試到暫停的時候都會顯示該值。
(gdb) run 3 Starting program: /home/tyruschin/ClionProjects/gdb_learning/test 3 Breakpoint 8, main (argc=2, argv=0x7fffffffde18) at gdb-01.c:33 33 printf("你輸入的值為:%d,計算結果為:%d\n", io -> value, io -> result); 4: argc = 2 3: *argv = 0x7fffffffe1c6 "/home/tyruschin/ClionProjects/gdb_learning/test" 2: argv = (char **) 0x7fffffffde18 1: argc = 2
單步調試:next(n)單步跟蹤,step(s)進入某個函數,finish返回調用的函數中,continue(c)表示繼續執行知道遇到斷點或結束。
(gdb) run 3 The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/tyruschin/ClionProjects/gdb_learning/test 3 Breakpoint 1, main (argc=2, argv=0x7fffffffde18) at gdb-01.c:19 19 if (NULL == io) { (gdb) s 25 if (argc != 2) { (gdb) s 30 io -> value = *argv[1] - '0'; (gdb) s 32 io -> result = sum(io -> value); (gdb) s sum (value=3) at gdb-01.c:39 39 int result = 0; (gdb) s 40 int i = 0; (gdb) finish Run till exit from #0 sum (value=3) at gdb-01.c:40 0x0000000000400639 in main (argc=2, argv=0x7fffffffde18) at gdb-01.c:32 32 io -> result = sum(io -> value); Value returned is $1 = 6 (gdb) s 33 printf("你輸入的值為:%d,計算結果為:%d\n", io -> value, io -> result); (gdb) c Continuing. 你輸入的值為:3,計算結果為:6 [Inferior 1 (process 27047) exited normally]
q表示退出GDB。。
附:書上的例子:
/*文件名:ex02-gdb-01.c*/ #include <stdio.h> /* 用於printf*/ #include <stdlib.h> /*用於malloc*/ /* 聲明函數sum為static int類型 */ static int sum(int value); /* 用於控制輸入輸出的結構 */ struct inout { int value; int result; }; int main(int argc, char * argv[]) { /*申請記憶體*/ struct inout * io = (struct inout * ) malloc(sizeof(struct inout)); /*判斷是否成功*/ if (NULL == io) { /*失敗返回*/ printf("申請記憶體失敗\n"); return -1; } /*判斷輸入參數是否正確*/ if (argc != 2) { printf("參數輸入錯誤!\n"); return -1; } /* 獲得輸入的參數 */ io -> value = *argv[1] - '0'; /* 對value進行累加求和 */ io -> result = sum(io -> value); printf("你輸入的值為:%d,計算結果為:%d\n", io -> value, io -> result); return 0; } /* 累加求和函數 */ static int sum(int value) { int result = 0; int i = 0; /* 迴圈計算累加值 */ for (i = 0; i < value; i++) result += (i + 1); /*返回結果*/ return result; }