Turbo C 程序的調(diào)試
一個(gè)程序設(shè)計(jì)好了以后, 通常會(huì)有一些錯(cuò)誤, 查找和修改程序中的錯(cuò)誤是令人頭痛的事。Turbo C集成開發(fā)環(huán)境提供了一調(diào)試裝置, 使得這一個(gè)工作容易了許多, 程序調(diào)試達(dá)到了編譯和運(yùn)行級(jí)。
一、TC消息窗口
使用TC最好的理由之一是它允許用戶修改語法錯(cuò)誤(編譯時(shí)) 和評(píng)估編譯器給出的警告。TC將編譯器和連接器發(fā)出的消息收集到一緩沖區(qū)中, 然后在消息窗口中顯示, 這樣在訪問源代碼的同時(shí), 還能一下看到這些消息。
現(xiàn)將上面的HELLO.C制造一點(diǎn)語法錯(cuò)誤, 將第一行包含語句的#去掉, 再去掉第五行printf語句中的后引號(hào),F(xiàn)在程序看上去是這樣的:
include
main()
{
printf("Hello, world\n);
}
按CTRL+F9重新編譯之。編譯窗口將顯示有多少錯(cuò)誤和警告: 應(yīng)為兩個(gè)錯(cuò)誤, 0個(gè)警告。
當(dāng)看見編譯窗口中的Press anykey提示時(shí), 按空格鍵, 消息窗口立刻被激活,亮條出現(xiàn)在第一個(gè)錯(cuò)誤或警告上, 這時(shí)編輯窗口中也會(huì)有一亮條--- 它標(biāo)志著編譯器給出的錯(cuò)誤或警告在源代碼中的相應(yīng)位置。
這時(shí)可用光標(biāo)鍵將消息窗口中的亮條上下移動(dòng), 注意到編輯窗口中的亮條也隨著跟蹤源代碼中錯(cuò)誤發(fā)生的位置。如果將亮條置于"compile"上, 則編輯器顯示文件的最后位置。
如果消息窗口太長看不見, 可用左、右光標(biāo)水平滾動(dòng)消息, 為了一次能夠多看點(diǎn)信息, 可按F5放大消息窗口。放大后, 編輯窗口不可見了, 因此不進(jìn)行錯(cuò)誤跟蹤,F(xiàn)在, 保持分屏模式。
為了改正錯(cuò)誤, 將消息窗口中的亮條置于第一個(gè)錯(cuò)誤消息上, 回車, 光標(biāo)移到編輯窗口中錯(cuò)誤產(chǎn)生處, 注意, 編輯器狀態(tài)給出所選消息( 這在放大模式下是有用的)改正之。(將第一行拿走的#重新寫上)。
當(dāng)不只一個(gè)錯(cuò)誤時(shí), 可用兩種方法來修改下一錯(cuò)誤。
第一種方法和前面一樣, 按F6回到消息窗口選擇想修改的下一條消息。
第二種方法不用回到消息窗口, 只要按Alt+F8, 編譯器就會(huì)將光標(biāo)移至消息窗口中列的下一個(gè)錯(cuò)誤。按Alt+F7可移至前一個(gè)錯(cuò)誤。
這兩種方法各有長短, 視情況而定。有時(shí)源代碼中一個(gè)愚蠢的錯(cuò)誤把編譯弄糊涂了, 產(chǎn)生好多消息, 這時(shí)選擇修改第一條消息就使得其余的一些錯(cuò)誤消息沒有什么意義了, 這種情況發(fā)生時(shí), 使用方法一會(huì)方便些, 一修改完第一個(gè)錯(cuò)誤之后回到消息窗口, 再滾動(dòng)到下一個(gè)有意義的消息上, 選擇之。在別的情況下, 按Alt+F8會(huì)方便得多。
記住, Alt+F7和Alt+F8是熱鍵, TC中無論何時(shí)均起作用。因此在消息窗口中按Alt+F8得到的不是當(dāng)前亮行消息, 而是下一個(gè)消息(按Enter選擇當(dāng)前消息)。但如果沒別的編譯消息, Alt+F8就不起作用了。
注: 可以如此法選擇連接消息, 但它們不跟蹤源文件。在修改語法錯(cuò)誤的過程當(dāng)中, 經(jīng)常需要增加、刪除正文, 編輯器是記住的, 依然能正確定位錯(cuò)誤位置。沒有必要記住行號(hào)和增加、刪除的正文行。
二、Turbo C集成調(diào)試器
一旦修改好語法錯(cuò)誤之后程序編譯就沒什么問題了, 但還是可能不按要求運(yùn)行, 因?yàn)榭赡苡羞壿嬪e(cuò)誤(運(yùn)行錯(cuò)誤)。這種錯(cuò)誤跟蹤就無助于發(fā)現(xiàn)錯(cuò)誤位置了。TC有一個(gè)集成調(diào)試器可以跟蹤運(yùn)行錯(cuò)誤。通過調(diào)試器可以運(yùn)行, 在斷點(diǎn)處暫停,檢查變量的值, 甚至可以改變之, 以看程序會(huì)有什么反應(yīng)。
Turbo C集成調(diào)試器是源程序級(jí)的調(diào)試器, 即用同你編寫程序一樣的" 語言"來控制調(diào)試器。例如, 為了顯示數(shù)組中的一個(gè)元素的值, 可告訴調(diào)試器顯示這樣的表達(dá)式的值:
Ctrl+F4 Debug/Eavluate 計(jì)算表達(dá)式, 允許修改變量的值。
Debug/Find Function 查找函數(shù)定義, 顯示在編輯窗口中。 僅
在調(diào)試時(shí)才有效。
Ctrl+F3 Debug/Call Stack 顯示調(diào)用棧, 可顯示任何函數(shù)的當(dāng)前執(zhí)
行位置, 其方法是在調(diào)用棧中選擇相應(yīng)的
函數(shù)名。僅在調(diào)試時(shí)有效。
Debug/Source Debugging 控制是否允許調(diào)試: 置為On時(shí), 集成調(diào)
試器和單獨(dú)調(diào)試器均可用 ; 置為
Standalone時(shí), 只能用單獨(dú)調(diào)試器
調(diào)試, 雖然還能在TC中運(yùn)行; 置為
None時(shí), 在.EXE文件不置調(diào)試信息,
兩種調(diào)試均不能調(diào)試。
Ctrl+F4 Break/Watch/Add Watch 增加一監(jiān)視表達(dá)式。
Break/Watch/Delete Watch 刪除一監(jiān)視表達(dá)式。
Break/Watch/Edit 編輯一監(jiān)視表達(dá)式。
Break/Watch/Remove All 刪除所有監(jiān)視表達(dá)式。
Watches
Ctrl+F8 Break/Watch/Toggle 設(shè)置或清除光標(biāo)所在行的斷點(diǎn)。
Breakpoint
Break/Watch/Clear 刪除程序中所有斷點(diǎn)。
Breakpoint
Break/Watch/Next 顯示下一斷點(diǎn)
Breakpoint
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
表3. 調(diào)試器菜單命令及其熱鍵
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
熱鍵 菜單命令 功能
───────────────────────────────────
F5 在整屏和分屏之間放大縮小活動(dòng)窗口。
Alt+F5 將顯示轉(zhuǎn)到用戶屏, 擊任意鍵返回。
F6 在編輯窗口與監(jiān)視窗口或消息窗口間
切換。
Alt+F6 若編輯窗口是活動(dòng)的, 轉(zhuǎn)到最近一次
裝入編輯器的文件; 若下面窗口是活
動(dòng)的, 則在監(jiān)視窗口和消息窗口間切換。
Ctrl+F9 Run/Run 調(diào)試運(yùn)行或不調(diào)試運(yùn)行程序, 必要時(shí)
編譯、連接源文件, 若編譯、 連接時(shí)
Debug/Source Debuging和O/C/C/OBJ
Debug Information為On, 則運(yùn)行程序
到斷點(diǎn)或程序末尾。
Project/Remove Messages 刪除消息窗口中的內(nèi)容。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
判斷程序是否出錯(cuò)或者為什么出錯(cuò)是編程中最有挑戰(zhàn)意義的一方面。這里建義你進(jìn)行預(yù)防性設(shè)計(jì), 具體做法為:
(1). 將代碼寫清楚點(diǎn), 應(yīng)作適當(dāng)縮進(jìn), 使用文字說明和描述性的變量名。
(2). 代碼應(yīng)簡(jiǎn)單, 把精力放在簡(jiǎn)單語句中的復(fù)雜表達(dá)式, 而不是一些復(fù)雜語句。Turbo C的代碼優(yōu)化機(jī)制將大大提高代碼的效率, 而且調(diào)試、閱讀、 修改起來容易。
(3). 盡量用目的簡(jiǎn)單、好定義的函數(shù)構(gòu)建程序。 這會(huì)便于編制調(diào)試程序和分析結(jié)果, 而且閱讀、修改起來也要容易一些。
(4). 應(yīng)盡量減少各個(gè)函數(shù)要求的數(shù)據(jù)和改變數(shù)據(jù)的元素個(gè)數(shù)。這也會(huì)便于編制測(cè)試程序和分析結(jié)果; 同樣便于閱讀、修改程序。并且還限制了出錯(cuò)函數(shù)可能造成的巨大混亂的牽涉面, 便得能在一個(gè)調(diào)試節(jié)中多運(yùn)行函數(shù)幾次。
(5). 要留心編寫程序中的公共函數(shù), 或者說在其它程序中可再用的函數(shù)。編寫、調(diào)試一個(gè)一般性的函數(shù)通常要比編寫、調(diào)試兩個(gè)或更多的特殊函數(shù)要容易。
Turbo C編譯、連接和運(yùn)行時(shí)的常見錯(cuò)誤
一、編譯時(shí)的常見錯(cuò)誤
1. 數(shù)據(jù)類型錯(cuò)誤。此類錯(cuò)誤是初學(xué)者編程時(shí)的常見現(xiàn)象, 下面是一些要引起注意的錯(cuò)誤:
(1) 所有變量和常量必須要加以說明。
(2) 變量只能賦給相同類型的數(shù)據(jù)。
(3) 對(duì)scanf()語句, 用戶可能輸入錯(cuò)誤類型的數(shù)據(jù)項(xiàng), 這將導(dǎo)致運(yùn)行時(shí)出錯(cuò), 并報(bào)出錯(cuò)信息。為避免這樣的錯(cuò)誤出現(xiàn), 你就提示用戶輸入正確類型的數(shù)據(jù)。
(4) 在執(zhí)行算術(shù)運(yùn)算時(shí)要注意:
a. 根據(jù)語法規(guī)則書寫雙精度數(shù)字。要寫0.5, 而不是寫.5; 要寫1.0, 而不是1。盡管C語言會(huì)自動(dòng)地把整型轉(zhuǎn)換成雙精度型, 但書寫雙精度型是個(gè)好習(xí)慣。讓C語言為你做強(qiáng)行轉(zhuǎn)換這是一種效率不高的程序設(shè)計(jì)風(fēng)格。 這有可能導(dǎo)致轉(zhuǎn)換產(chǎn)生錯(cuò)誤。
b. 不要用0除。這是一個(gè)災(zāi)難性的錯(cuò)誤, 它會(huì)導(dǎo)致程序失敗, 不管C語言的什么版本, 都是如此, 執(zhí)行除法運(yùn)算要特別小心。
c. 確保所有的雙精度數(shù)(包括那些程序輸入用的雙精度數(shù)) 是在實(shí)數(shù)范圍之內(nèi)。
d. 所有整數(shù)必須在整數(shù)允許的范圍內(nèi)。這適用于所有計(jì)算結(jié)果, 包括中間結(jié)果。
2. 將函數(shù)后面的";"忘掉。此時(shí)錯(cuò)誤提示色棒將停在該語句下的一行, 并顯示:
Statement missing ; in function <函數(shù)名>
3. 給宏指令如#include, #define等語句尾加了";"號(hào)。
4. "{"和"}"、"("和")"、"/*"和"*/"不匹配。 引時(shí)色棒將位于錯(cuò)誤所在的行, 并提示出有關(guān)丟掉括號(hào)的信息。
5. 沒有用#include指令說明頭文件, 錯(cuò)誤信息提示有關(guān)該函數(shù)所使用的參數(shù)未定義。
6. 使用了Turbo C保留關(guān)鍵字作為標(biāo)識(shí)符, 此時(shí)將提示定義了太多數(shù)據(jù)類型。
7. 將定義變量語句放在了執(zhí)行語句后面。此時(shí)會(huì)提示語法錯(cuò)誤。
8. 使用了未定義的變量, 此時(shí)屏幕顯示:
Undefined symbol '<變量名>' in function <函數(shù)名>
9. 警告錯(cuò)誤太多。忽略這些警告錯(cuò)誤并不影響程序的執(zhí)行和結(jié)果。編譯時(shí)當(dāng)警告錯(cuò)誤數(shù)目大于某一規(guī)定值時(shí)(缺省為100)便退出編譯器, 這時(shí)應(yīng)改變集成開發(fā)環(huán)境Options/Compiler/Errors中的有關(guān)警告錯(cuò)誤檢查開關(guān)為off。
10. 將關(guān)系符"=="誤用作賦值號(hào)"="。此時(shí)屏幕顯示:
Lvalue required in function <函數(shù)名>
二、連接時(shí)的常見錯(cuò)誤
1. 將Turbo C庫函數(shù)名寫錯(cuò)。這種情況下在連接時(shí)將會(huì)認(rèn)為此函數(shù)是用戶自定義函數(shù)。此時(shí)屏幕顯示:
Undefined symbol '<函數(shù)名>' in <程序名>
2. 多個(gè)文件連接時(shí), 沒有在"Project/Project name中指定項(xiàng)目文件 (.PRJ 文件), 此時(shí)出現(xiàn)找不到函數(shù)的錯(cuò)誤。
3. 子函數(shù)在說明和定義時(shí)類型不一致。
4. 程序調(diào)用的子函數(shù)沒有定義。
三、運(yùn)行時(shí)的常見錯(cuò)誤
1. 路徑名錯(cuò)誤。在MS-DOS中, 斜杠(\)表示一個(gè)目錄名; 而在Turbo C 中斜杠是個(gè)某個(gè)字符串的一個(gè)轉(zhuǎn)義字符, 這樣, 在用Turbo C 字符串給出一個(gè)路徑名時(shí)應(yīng)考慮"\"的轉(zhuǎn)義的作用。例如, 有這樣一條語句:
file=fopen("c:\new\tbc.dat", "rb");
目的是打開C盤中NEW目錄中的TBC.DAT文件, 但做不到。這里"\"后面緊接的分別是"n"及"t", "\n"及"\t"將被分別編譯為換行及tab字符, DOS將認(rèn)為它是不正確的文件名而拒絕接受, 因?yàn)槲募胁荒芎蛽Q行或tab字符。正確的寫法應(yīng)為:
file=fopen("c:\\new\\tbc.dat", "rb");
2. 格式化輸入輸出時(shí), 規(guī)定的類型與變量本身的類型不一致。例如:
float l;
printf("%c", l);
3. scanf()函數(shù)中將變量地址寫成變量。例如:
int l;
scanf("%d", l);
4. 循環(huán)語句中, 循環(huán)控制變量在每次循環(huán)未進(jìn)行修改, 使循環(huán)成為無限循環(huán)。
5. switch語句中沒有使用break語句。
6. 將賦值號(hào)"="誤用作關(guān)系符"=="。
7. 多層條件語句的if和else不配對(duì)。
8. 用動(dòng)態(tài)內(nèi)存分配函數(shù)malloc()或calloc()分配的內(nèi)存區(qū)使用完之后, 未用free()函數(shù)釋放, 會(huì)導(dǎo)致函數(shù)前幾次調(diào)用正常, 而后面調(diào)用時(shí)發(fā)生死機(jī)現(xiàn)象,不能返回操作系統(tǒng)。其原因是因?yàn)闆]用空間可供分配, 而占用了操作系統(tǒng)在內(nèi)存中的某些空間。
9. 使用了動(dòng)態(tài)分配內(nèi)存不成功的指針, 造成系統(tǒng)破壞。
10. 在對(duì)文件操作時(shí), 沒有在使用完及時(shí)關(guān)閉打開的文件。
相關(guān)推薦:計(jì)算機(jī)等考二級(jí)C語言備考:C語言/C++編譯過程北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |