Linux下C應用程序開(kāi)發(fā)
本節用一個(gè)實(shí)例教你一步步的用 gdb 調試程序. 被調試的程序相當的簡(jiǎn)單, 但它展示了 gdb 的典型應用.
下面列出了將被調試的程序. 這個(gè)程序被稱(chēng)為 hello , 它顯示一個(gè)簡(jiǎn)單的問(wèn)候, 再用反序將它列出.
#include stdio.h>;
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] = '';
printf (The string printed backward is %s , string2);
}
用下面的命令編譯它:
}
用下面的命令編譯它:
gcc -g -o hello hello.c
這個(gè)程序執行時(shí)顯示如下結果:
../hello
The string is hello world!
這個(gè)程序執行時(shí)顯示如下結果:
../hello
The string is hello world!
The string printed backward is
輸出的第一行是正確的, 但第二行打印出的東西并不是我們所期望的. 我們所設想的輸出
應該是:
輸出的第一行是正確的, 但第二行打印出的東西并不是我們所期望的. 我們所設想的輸出
應該是:
The string printed backward is !dlrow olleh
由于某些原因, my_print2 函數沒(méi)有正常工作. 讓我們用 gdb 看看問(wèn)題究竟出在哪兒,
先鍵入如下命令:
由于某些原因, my_print2 函數沒(méi)有正常工作. 讓我們用 gdb 看看問(wèn)題究竟出在哪兒,
先鍵入如下命令:
gdb hello
------------------------------------------------------------------------------
--
--
注意: 記得在編譯 hello 程序時(shí)把調試選項打開(kāi).
------------------------------------------------------------------------------
--
--
如果你在輸入命令時(shí)忘了把要調試的程序作為參數傳給 gdb , 你可以在 gdb 提示符下用
file 命令來(lái)載入它:
file 命令來(lái)載入它:
(gdb) file hello
這個(gè)命令將載入 hello 可執行文件就象你在 gdb 命令行里裝入它一樣.
這個(gè)命令將載入 hello 可執行文件就象你在 gdb 命令行里裝入它一樣.
這時(shí)你能用 gdb 的 run 命令來(lái)運行 hello 了. 當它在 gdb 里被運行后結果大約會(huì )象這樣:
(gdb) run
Starting program: /root/hello
The string is hello world!
The string printed backward is
Program exited with code 040
這個(gè)輸出和在 gdb 外面運行的結果一樣. 問(wèn)題是, 為什么反序打印沒(méi)有工作? 為了找出癥結所在, 我們可以在 my_print2 函數的 for 語(yǔ)句后設一個(gè)斷點(diǎn), 具體的做法是在 gdb
提示符下鍵入 list 命令三次, 列出源代碼:
這個(gè)輸出和在 gdb 外面運行的結果一樣. 問(wèn)題是, 為什么反序打印沒(méi)有工作? 為了找出癥結所在, 我們可以在 my_print2 函數的 for 語(yǔ)句后設一個(gè)斷點(diǎn), 具體的做法是在 gdb
提示符下鍵入 list 命令三次, 列出源代碼:
(gdb) list
(gdb) list
(gdb) list
------------------------------------------------------------------------------
--
--
技巧: 在 gdb 提示符下按回車(chē)健將重復上一個(gè)命令.
------------------------------------------------------------------------------
--
--
第一次鍵入 list 命令的輸出如下:
1 #include stdio.h>;
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);
如果按下回車(chē), 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;
再按一次回車(chē)將列出 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;
再按一次回車(chē)將列出 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 }
根據列出的源程序, 你能看到要設斷點(diǎn)的地方在第26行, 在 gdb 命令行提示符下鍵入如下命令設置斷點(diǎn):
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 }
根據列出的源程序, 你能看到要設斷點(diǎn)的地方在第26行, 在 gdb 命令行提示符下鍵入如下命令設置斷點(diǎn):
(gdb) break 26
gdb 將作出如下的響應:
gdb 將作出如下的響應:
Breakpoint 1 at 0x804857c: file hello.c, line 26.
(gdb)
現在再鍵入 run 命令, 將產(chǎn)生如下的輸出:
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;
你能通過(guò)設置一個(gè)觀(guān)察 string2[size - i] 變量的值的觀(guān)察點(diǎn)來(lái)看出錯誤是怎樣產(chǎn)生的,
做法是鍵入:
26 string2[size - i] = string;
你能通過(guò)設置一個(gè)觀(guān)察 string2[size - i] 變量的值的觀(guān)察點(diǎn)來(lái)看出錯誤是怎樣產(chǎn)生的,
做法是鍵入:
(gdb) watch string2[size - i]
gdb 將作出如下回應:
gdb 將作出如下回應:
Hardware watchpoint 2: string2[size - i]
現在可以用 next 命令來(lái)一步步的執行 for 循環(huán)了:
現在可以用 next 命令來(lái)一步步的執行 for 循環(huán)了:
(gdb) next
經(jīng)過(guò)第一次循環(huán)后, gdb 告訴我們 string2[size - i] 的值是 `h`. gdb 用如下的顯示來(lái)告訴你這個(gè)信息:
經(jīng)過(guò)第一次循環(huán)后, gdb 告訴我們 string2[size - i] 的值是 `h`. gdb 用如下的顯示來(lái)告訴你這個(gè)信息:
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++)
這個(gè)值正是期望的. 后來(lái)的數次循環(huán)的結果都是正確的. 當 i=11 時(shí), 表達式
string2[size - i] 的值等于 `!`, size - i 的值等于 1, 最后一個(gè)字符已經(jīng)拷到新串里了.
New value = 104 'h'
my_print2 (string=0xbffffab0 hello world!) at hello.c:25
25 for (i = 0; i size; i++)
這個(gè)值正是期望的. 后來(lái)的數次循環(huán)的結果都是正確的. 當 i=11 時(shí), 表達式
string2[size - i] 的值等于 `!`, size - i 的值等于 1, 最后一個(gè)字符已經(jīng)拷到新串里了.
如果你再把循環(huán)執行下去, 你會(huì )看到已經(jīng)沒(méi)有值分配給 string2[0] 了, 而它是新串的第一個(gè)字符, 因為 malloc 函數在分配內存時(shí)把它們初始化為空(null)字符. 所以 string2 的第一個(gè)字符是空字符. 這解釋了為什么在打印 string2 時(shí)沒(méi)有任何輸出了.
現在找出了問(wèn)題出在哪里, 修正這個(gè)錯誤是很容易的. 你得把代碼里寫(xiě)入 string2 的第一個(gè)字符的的偏移量改為 size - 1 而不是 size. 這是因為 string2 的大小為 12, 但起始偏移量是 0, 串內的字符從偏移量 0 到 偏移量 10, 偏移量 11 為空字符保留.
改正方法非常簡(jiǎn)單. 這是這種解決辦法的代碼:
#include stdio.h>;
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] = '';
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
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);
}
如果程序產(chǎn)生了core文件,可以用gdb hello core命令來(lái)查看程序在何處出錯。如在函數my_print2()中,如果忘記了給string2分配內存 string2 = (char *) malloc (size + 1);,很可能就會(huì ) core dump. linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)
}
如果程序產(chǎn)生了core文件,可以用gdb hello core命令來(lái)查看程序在何處出錯。如在函數my_print2()中,如果忘記了給string2分配內存 string2 = (char *) malloc (size + 1);,很可能就會(huì ) core dump. linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)
linux相關(guān)文章:linux教程
關(guān)鍵詞:
程序開(kāi)發(fā)
應用
Linux
相關(guān)推薦
技術(shù)專(zhuān)區
- FPGA
- DSP
- MCU
- 示波器
- 步進(jìn)電機
- Zigbee
- LabVIEW
- Arduino
- RFID
- NFC
- STM32
- Protel
- GPS
- MSP430
- Multisim
- 濾波器
- CAN總線(xiàn)
- 開(kāi)關(guān)電源
- 單片機
- PCB
- USB
- ARM
- CPLD
- 連接器
- MEMS
- CMOS
- MIPS
- EMC
- EDA
- ROM
- 陀螺儀
- VHDL
- 比較器
- Verilog
- 穩壓電源
- RAM
- AVR
- 傳感器
- 可控硅
- IGBT
- 嵌入式開(kāi)發(fā)
- 逆變器
- Quartus
- RS-232
- Cyclone
- 電位器
- 電機控制
- 藍牙
- PLC
- PWM
- 汽車(chē)電子
- 轉換器
- 電源管理
- 信號放大器
評論