gdb 應用舉例?
本節用一個實例教你一步步的用 gdb 調試程序. 被調試的程序相當的簡單, 但它展示了 gdb 的典型應用.
本節用一個實例教你一步步的用 gdb 調試程序. 被調試的程序相當的簡單, 但它展示了 gdb 的典型應用.
下面列出了將被調試的程序. 這個程序被稱為 hello , 它顯示一個簡單的問候, 再用反序將它列出.
#include ;
static void my_print (char *);?
static void my_print2 (char *);
static void my_print2 (char *);
main ()?
{?
char my_string[] = "hello world!";?
my_print (my_string);?
my_print2 (my_string);?
}
{?
char my_string[] = "hello world!";?
my_print (my_string);?
my_print2 (my_string);?
}
void my_print (char *string)?
{?
printf ("The string is %s ", string);?
}
{?
printf ("The string is %s ", string);?
}
void my_print2 (char *string)?
{?
char *string2;?
int size, i;
{?
char *string2;?
int size, i;
size = strlen (string);?
string2 = (char *) malloc (size + 1);?
for (i = 0; i < size; i++)?
string2[size - i] = string;?
string2[size+1] = '';
string2 = (char *) malloc (size + 1);?
for (i = 0; i < size; i++)?
string2[size - i] = string;?
string2[size+1] = '';
gcc -g -o hello hello.c?
這個程序執行時顯示如下結果:?
../hello?
The string is hello world!
這個程序執行時顯示如下結果:?
../hello?
The string is hello world!
The string printed backward is?
輸出的第一行是正確的, 但第二行打印出的東西并不是我們所期望的. 我們所設想的輸出?
應該是:
輸出的第一行是正確的, 但第二行打印出的東西并不是我們所期望的. 我們所設想的輸出?
應該是:
The string printed backward is !dlrow olleh?
由于某些原因, my_print2 函數沒有正常工作. 讓我們用 gdb 看看問題究竟出在哪兒,?
先鍵入如下命令:
由于某些原因, my_print2 函數沒有正常工作. 讓我們用 gdb 看看問題究竟出在哪兒,?
先鍵入如下命令:
gdb hello
------------------------------------------------------------------------------?
--
--
注意: 記得在編譯 hello 程序時把調試選項打開.
------------------------------------------------------------------------------?
--
--
如果你在輸入命令時忘了把要調試的程序作為參數傳給 gdb , 你可以在 gdb 提示符下用?
file 命令來載入它:
file 命令來載入它:
(gdb) file hello?
這個命令將載入 hello 可執行文件就象你在 gdb 命令行里裝入它一樣.
這個命令將載入 hello 可執行文件就象你在 gdb 命令行里裝入它一樣.
這時你能用 gdb 的 run 命令來運行 hello 了. 當它在 gdb 里被運行后結果大約會象這樣:
(gdb) run
Starting program: /root/hello
The string is hello world!
The string printed backward is
Program exited with code 040?
這個輸出和在 gdb 外面運行的結果一樣. 問題是, 為什么反序打印沒有工作? 為了找出癥結所在, 我們可以在 my_print2 函數的 for 語句后設一個斷點, 具體的做法是在 gdb?
提示符下鍵入 list 命令三次, 列出源代碼:
這個輸出和在 gdb 外面運行的結果一樣. 問題是, 為什么反序打印沒有工作? 為了找出癥結所在, 我們可以在 my_print2 函數的 for 語句后設一個斷點, 具體的做法是在 gdb?
提示符下鍵入 list 命令三次, 列出源代碼:
(gdb) list
(gdb) list
(gdb) list
------------------------------------------------------------------------------?
--
--
技巧: 在 gdb 提示符下按回車健將重復上一個命令.
------------------------------------------------------------------------------?
--
--
第一次鍵入 list 命令的輸出如下:
1 #include ;?
2?
3 static void my_print (char *);?
4 static void my_print2 (char *);?
5?
6 main ()?
7 {?
8 char my_string[] = "hello world!";?
9 my_print (my_string);?
10 my_print2 (my_string);
2?
3 static void my_print (char *);?
4 static void my_print2 (char *);?
5?
6 main ()?
7 {?
8 char my_string[] = "hello world!";?
9 my_print (my_string);?
10 my_print2 (my_string);
如果按下回車, gdb 將再執行一次 list 命令, 給出下列輸出:
11 }?
12?
13 void my_print (char *string)?
14 {?
15 printf ("The string is %s ", string);?
16 }?
17?
18 void my_print2 (char *string)?
19 {?
20 char *string2;?
再按一次回車將列出 hello 程序的剩余部分:
12?
13 void my_print (char *string)?
14 {?
15 printf ("The string is %s ", string);?
16 }?
17?
18 void my_print2 (char *string)?
19 {?
20 char *string2;?
再按一次回車將列出 hello 程序的剩余部分:
21 int size, i;?
22?
23 size = strlen (string);?
24 string2 = (char *) malloc (size + 1);?
25 for (i = 0; i < size; i++)?
26 string2[size - i] = string;?
27 string2[size+1] = '';?
28?
29 printf ("The string printed backward is %s ", string2);?
30 }?
根據列出的源程序, 你能看到要設斷點的地方在第26行, 在 gdb 命令行提示符下鍵入如下命令設置斷點:
22?
23 size = strlen (string);?
24 string2 = (char *) malloc (size + 1);?
25 for (i = 0; i < size; i++)?
26 string2[size - i] = string;?
27 string2[size+1] = '';?
28?
29 printf ("The string printed backward is %s ", string2);?
30 }?
根據列出的源程序, 你能看到要設斷點的地方在第26行, 在 gdb 命令行提示符下鍵入如下命令設置斷點:
(gdb) break 26?
gdb 將作出如下的響應:
gdb 將作出如下的響應:
Breakpoint 1 at 0x804857c: file hello.c, line 26.
(gdb)
現在再鍵入 run 命令, 將產生如下的輸出:
Starting program: /root/hello
The string is hello world!
Breakpoint 1, my_print2 (string=0xbffffab0 "hello world!") at hello.c:26?
26 string2[size - i] = string;?
你能通過設置一個觀察 string2[size - i] 變量的值的觀察點來看出錯誤是怎樣產生的,?
做法是鍵入:
26 string2[size - i] = string;?
你能通過設置一個觀察 string2[size - i] 變量的值的觀察點來看出錯誤是怎樣產生的,?
做法是鍵入:
(gdb) watch string2[size - i]?
gdb 將作出如下回應:
gdb 將作出如下回應:
Hardware watchpoint 2: string2[size - i]?
現在可以用 next 命令來一步步的執行 for 循環了:
現在可以用 next 命令來一步步的執行 for 循環了:
(gdb) next?
經過第一次循環后, gdb 告訴我們 string2[size - i] 的值是 `h`. gdb 用如下的顯示來告訴你這個信息:
經過第一次循環后, gdb 告訴我們 string2[size - i] 的值是 `h`. gdb 用如下的顯示來告訴你這個信息:
Hardware watchpoint 2: string2[size - i]
Old value = 0 '00'?
New value = 104 'h'?
my_print2 (string=0xbffffab0 "hello world!") at hello.c:25?
25 for (i = 0; i < size; i++)?
這個值正是期望的. 后來的數次循環的結果都是正確的. 當 i=11 時, 表達式?
string2[size - i] 的值等于 `!`, size - i 的值等于 1, 最后一個字符已經拷到新串里了.
New value = 104 'h'?
my_print2 (string=0xbffffab0 "hello world!") at hello.c:25?
25 for (i = 0; i < size; i++)?
這個值正是期望的. 后來的數次循環的結果都是正確的. 當 i=11 時, 表達式?
string2[size - i] 的值等于 `!`, size - i 的值等于 1, 最后一個字符已經拷到新串里了.
如果你再把循環執行下去, 你會看到已經沒有值分配給 string2[0] 了, 而它是新串的第一個字符, 因為 malloc 函數在分配內存時把它們初始化為空(null)字符. 所以 string2 的第一個字符是空字符. 這解釋了為什么在打印 string2 時沒有任何輸出了.
?
現在找出了問題出在哪里, 修正這個錯誤是很容易的. 你得把代碼里寫入 string2 的第一個字符的的偏移量改為 size - 1 而不是 size. 這是因為 string2 的大小為 12, 但起始偏移量是 0, 串內的字符從偏移量 0 到 偏移量 10, 偏移量 11 為空字符保留.
改正方法非常簡單. 這是這種解決辦法的代碼:
#include ;
static void my_print (char *);?
static void my_print2 (char *);
static void my_print2 (char *);
main ()?
{?
char my_string[] = "hello world!";?
my_print (my_string);?
my_print2 (my_string);?
}
{?
char my_string[] = "hello world!";?
my_print (my_string);?
my_print2 (my_string);?
}
void my_print (char *string)?
{?
printf ("The string is %s ", string);?
}
{?
printf ("The string is %s ", string);?
}
void my_print2 (char *string)?
{?
char *string2;?
int size, i;
{?
char *string2;?
int size, i;
size = strlen (string);?
string2 = (char *) malloc (size + 1);?
for (i = 0; i < size; i++)?
string2[size -1 - i] = string;?
string2[size] = '';
string2 = (char *) malloc (size + 1);?
for (i = 0; i < size; i++)?
string2[size -1 - i] = string;?
string2[size] = '';
printf ("The string printed backward is %s ", string2);?
}?
如果程序產生了core文件,可以用gdb hello core命令來查看程序在何處出錯。如在函數my_print2()中,如果忘記了給string2分配內存 string2 = (char *) malloc (size + 1);,很可能就會 core dump.
}?
如果程序產生了core文件,可以用gdb hello core命令來查看程序在何處出錯。如在函數my_print2()中,如果忘記了給string2分配內存 string2 = (char *) malloc (size + 1);,很可能就會 core dump.
評論