?? 00000010.htm
字號(hào):
char *string2; <br /> int size, i; <br /> size = strlen (string); <br /> string2 = (char *) malloc (size + 1); <br /> for (i = 0; i < size; i++) <br /> string2[size - i] = string[i]; <br /> string2[size+1] = `\0'; <br /> printf ("The string printed backward is %s\n", string2); <br />} <br /> 用下面的命令編譯它: <br />gcc -o test test.c <br /> 這個(gè)程序執(zhí)行時(shí)顯示如下結(jié)果: <br />The string is hello there <br />The string printed backward is <br /> 輸出的第一行是正確的, 但第二行打印出的東西并不是我們所期望的. 我們所設(shè)想 <br />的輸出應(yīng)該是: <br />The string printed backward is ereht olleh <br /> 由于某些原因, my_print2 函數(shù)沒(méi)有正常工作. 讓我們用 gdb 看看問(wèn)題究竟出在 <br />哪兒, 先鍵入如下命令: <br />gdb greeting <br />---------------------------------------------------------------------------- <br />---- <br />注意: 記得在編譯 greeting 程序時(shí)把調(diào)試選項(xiàng)打開(kāi). <br />---------------------------------------------------------------------------- <br />---- <br /> 如果你在輸入命令時(shí)忘了把要調(diào)試的程序作為參數(shù)傳給 gdb , 你可以在 gdb 提示 <br />符下用 file 命令來(lái)載入它: <br />(gdb) file greeting <br /> 這個(gè)命令將載入 greeting 可執(zhí)行文件就象你在 gdb 命令行里裝入它一樣. <br /> 這時(shí)你能用 gdb 的 run 命令來(lái)運(yùn)行 greeting 了. 當(dāng)它在 gdb 里被運(yùn)行后結(jié)果大 <br />約會(huì)象這樣: <br />(gdb) run <br />Starting program: /root/greeting <br />The string is hello there <br />The string printed backward is <br />Program exited with code 041 <br /> 這個(gè)輸出和在 gdb 外面運(yùn)行的結(jié)果一樣. 問(wèn)題是, 為什么反序打印沒(méi)有工作? 為了 <br />找出癥結(jié)所在, 我們可以在 my_print2 函數(shù)的 for 語(yǔ)句后設(shè)一個(gè)斷點(diǎn), 具體的做法是 <br />在 gdb 提示符下鍵入 list 命令三次, 列出源代碼: <br />(gdb) list <br />(gdb) list <br />(gdb) list <br />---------------------------------------------------------------------------- <br />---- <br />技巧: 在 gdb 提示符下按回車(chē)健將重復(fù)上一個(gè)命令. <br />---------------------------------------------------------------------------- <br />---- <br /> 第一次鍵入 list 命令的輸出如下: <br />1 #include <stdio.h> <br />2 <br />3 main () <br />4 { <br />5 char my_string[] = "hello there"; <br />6 <br />7 my_print (my_string); <br />8 my_print2 (my_string); <br />9 } <br />10 <br /> 如果按下回車(chē), gdb 將再執(zhí)行一次 list 命令, 給出下列輸出: <br />11 my_print (char *string) <br />12 { <br />13 printf ("The string is %s\n", string); <br />14 } <br />15 <br />16 my_print2 (char *string) <br />17 { <br />18 char *string2; <br />19 int size, i; <br />20 <br /> 再按一次回車(chē)將列出 greeting 程序的剩余部分: <br />21 size = strlen (string); <br />22 string2 = (char *) malloc (size + 1); <br />23 for (i = 0; i < size; i++) <br />24 string2[size - i] = string[i]; <br />25 string2[size+1] = `\0'; <br />26 printf ("The string printed backward is %s\n", string2); <br />27 } <br /> 根據(jù)列出的源程序, 你能看到要設(shè)斷點(diǎn)的地方在第24行, 在 gdb 命令行提示符下鍵 <br />入如下命令設(shè)置斷點(diǎn): <br />(gdb) break 24 <br /> gdb 將作出如下的響應(yīng): <br />Breakpoint 1 at 0x139: file greeting.c, line 24 <br />(gdb) <br /> 現(xiàn)在再鍵入 run 命令, 將產(chǎn)生如下的輸出: <br />Starting program: /root/greeting <br />The string is hello there <br />Breakpoint 1, my_print2 (string = 0xbfffdc4 "hello there") at greeting.c :24 <br /> <br />24 string2[size-i]=string[i] <br /> 你能通過(guò)設(shè)置一個(gè)觀察 string2[size - i] 變量的值的觀察點(diǎn)來(lái)看出錯(cuò)誤是怎樣產(chǎn) <br />生的, 做法是鍵入: <br />(gdb) watch string2[size - i] <br /> gdb 將作出如下回應(yīng): <br />Watchpoint 2: string2[size - i] <br /> 現(xiàn)在可以用 next 命令來(lái)一步步的執(zhí)行 for 循環(huán)了: <br />(gdb) next <br /> 經(jīng)過(guò)第一次循環(huán)后, gdb 告訴我們 string2[size - i] 的值是 `h`. gdb 用如下 <br />的顯示來(lái)告訴你這個(gè)信息: <br />Watchpoint 2, string2[size - i] <br />Old value = 0 `\000' <br />New value = 104 `h' <br />my_print2(string = 0xbfffdc4 "hello there") at greeting.c:23 <br />23 for (i=0; i<size; i++) <br /> 這個(gè)值正是期望的. 后來(lái)的數(shù)次循環(huán)的結(jié)果都是正確的. 當(dāng) i=10 時(shí), 表達(dá)式 str <br />ing2[size - i] 的值等于 `e`, size - i 的值等于 1, 最后一個(gè)字符已經(jīng)拷到新串里 <br />了. <br /> 如果你再把循環(huán)執(zhí)行下去, 你會(huì)看到已經(jīng)沒(méi)有值分配給 string2[0] 了, 而它是新 <br />串的第一個(gè)字符, 因?yàn)?amp;nbsp;malloc 函數(shù)在分配內(nèi)存時(shí)把它們初始化為空(null)字符. 所以 <br /> string2 的第一個(gè)字符是空字符. 這解釋了為什么在打印 string2 時(shí)沒(méi)有任何輸出了 <br />. <br /> 現(xiàn)在找出了問(wèn)題出在哪里, 修正這個(gè)錯(cuò)誤是很容易的. 你得把代碼里寫(xiě)入 string2 <br /> 的第一個(gè)字符的的偏移量改為 size - 1 而不是 size. 這是因?yàn)?amp;nbsp;string2 的大小為 <br />12, 但起始偏移量是 0, 串內(nèi)的字符從偏移量 0 到 偏移量 10, 偏移量 11 為空字符保 <br />留. <br /> 為了使代碼正常工作有很多種修改辦法. 一種是另設(shè)一個(gè)比串的實(shí)際大小小 1 的變 <br />量. 這是這種解決辦法的代碼: <br />#include <stdio.h> <br />main () <br />{ <br /> char my_string[] = "hello there"; <br /> my_print (my_string); <br /> my_print2 (my_string); <br />} <br />my_print (char *string) <br />{ <br /> printf ("The string is %s\n", string); <br />} <br />my_print2 (char *string) <br />{ <br /> char *string2; <br /> int size, size2, i; <br /> size = strlen (string); <br /> size2 = size -1; <br /> string2 = (char *) malloc (size + 1); <br /> for (i = 0; i < size; i++) <br /> string2[size2 - i] = string[i]; <br /> string2[size] = `\0'; <br /> printf ("The string printed backward is %s\n", string2); <br />} <br />另外的 C 編程工具 <br /> Slackware Linux 的發(fā)行版中還包括一些我們尚未提到的 C 開(kāi)發(fā)工具. 本節(jié)將介紹 <br />這些工具和它們的典型用法. <br />xxgdb <br /> xxgdb 是 gdb 的一個(gè)基于 X Window 系統(tǒng)的圖形界面. xxgdb 包括了命令行版的 <br /> gdb 上的所有特性. xxgdb 使你能通過(guò)按按鈕來(lái)執(zhí)行常用的命令. 設(shè)置了斷點(diǎn)的地方 <br />也用圖形來(lái)顯示. <br /> 你能在一個(gè) Xterm 窗口里鍵入下面的命令來(lái)運(yùn)行它: <br />xxgdb <br /> 你能用 gdb 里任何有效的命令行選項(xiàng)來(lái)初始化 xxgdb . 此外 xxgdb 也有一些特有 <br />的命令行選項(xiàng), 表 27.2 列出了這些選項(xiàng). <br /> 表 27.2. xxgdb 命令行選項(xiàng). <br />選 項(xiàng) 描 述 <br />db_name 指定所用調(diào)試器的名字, 缺省是 gdb. <br />db_prompt 指定調(diào)試器提示符, 缺省為 gdb. <br />gdbinit 指定初始化 gdb 的命令文件的文件名, 缺省為 .gdbinit. <br />nx 告訴 xxgdb 不執(zhí)行 .gdbinit 文件. <br />bigicon 使用大圖標(biāo). <br />calls <br /> 你可以在 sunsite.unc.edu FTP 站點(diǎn)用下面的路徑: <br />/pub/Linux/devel/lang/c/calls.tar.Z <br /> 來(lái)取得 calls , 一些舊版本的 Linux CD-ROM 發(fā)行版里也附帶有. 因?yàn)樗且粋€(gè)有 <br />用的工具, 我們?cè)谶@里也介紹一下. 如果你覺(jué)得有用的話, 從 BBS, FTP, 或另一張CD- <br />ROM 上弄一個(gè)拷貝. calls 調(diào)用 GCC 的預(yù)處理器來(lái)處理給出的源程序文件, 然后輸出 <br />這些文件的里的函數(shù)調(diào)用樹(shù)圖. <br />---------------------------------------------------------------------------- <br />---- <br />注意: 在你的系統(tǒng)上安裝 calls , 以超級(jí)用戶身份登錄后執(zhí)行下面的步驟: 1. 解壓和 <br /> untar 文件. 2. cd 進(jìn)入 calls untar 后建立的子目錄. 3. 把名叫 calls 的文件移 <br />動(dòng)到 /usr/bin 目錄. 4. 把名叫 calls.1 的文件移動(dòng)到目錄 /usr/man/man1 . 5. 刪 <br />除 /tmp/calls 目錄. 這些步驟將把 calls 程序和它的指南頁(yè)安裝載你的系統(tǒng)上. <br />---------------------------------------------------------------------------- <br />---- <br /> 當(dāng) calls 打印出調(diào)用跟蹤結(jié)果時(shí), 它在函數(shù)后面用中括號(hào)給出了函數(shù)所在文件的文 <br />件名: <br />
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -