版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、第7章 Delphi異常處理與調(diào)試,7.1 Delphi異常處理 7.2 Delphi異常類 7.3 Delphi異常處理機(jī)制 7.4 Delphi調(diào)試器 7.5 控制程序的運(yùn)行 7.6 斷點(diǎn) 7.7 監(jiān)視表達(dá)式的值 7.8 實(shí)驗(yàn),7.1 Delphi異常處理,7.1.1 異常處理的意義 異??梢岳斫鉃橐环N特殊的事件。當(dāng)這種特殊的事件發(fā)生時(shí),程序正常的執(zhí)行流程將被打斷。異常處理機(jī)制能夠確保在發(fā)生異常的情況下應(yīng)用程序不會(huì)中止運(yùn)行,也不會(huì)丟失數(shù)據(jù)或資源。 沒有人能保證程序代碼絕對(duì)不出錯(cuò)。有時(shí)候,即使程序本身沒有錯(cuò),但與程序打交道的軟、硬件設(shè)備出錯(cuò),也會(huì)使程序出現(xiàn)異常。引起異常的設(shè)備稱為“異常源”,
2、包括操作系統(tǒng)、設(shè)備驅(qū)動(dòng)程序、數(shù)據(jù)庫驅(qū)動(dòng)程序(諸如BDE、SQL Links、ODBC、ADO)、動(dòng)態(tài)鏈接庫、常駐內(nèi)存的防病毒軟件、Delphi自身的組件庫和運(yùn)行期庫等。,異常幾乎是不可避免的。過去,在沒有異常處理機(jī)制的情況下,程序員不得不小心翼翼地檢查每一次函數(shù)調(diào)用的返回值,或者通過額外的代碼捕獲可能的錯(cuò)誤。 關(guān)鍵是,通過檢查函數(shù)的返回值或設(shè)置錯(cuò)誤陷阱只能捕獲可預(yù)見的錯(cuò)誤。如果發(fā)生沒有預(yù)見到的錯(cuò)誤,或者函數(shù)調(diào)用本身就已失敗,則程序正常的流程將被打亂。 還有一個(gè)問題就是,程序中過多的錯(cuò)誤檢查代碼也破壞了程序的可讀性。事實(shí)上,這些代碼大都是閑置的,因?yàn)槌绦蛑械教幇l(fā)生異常的可能性畢竟不是很大。 使用
3、Object Pascal語言的異常處理機(jī)制,就能解決上述弊端。它既能使程序的安全性得到保證,又不至于使程序代碼過分瑣碎。下面先看一段沒有采用異常處理機(jī)制的代碼:,var AChar,AString:ShortString; begin AString:=Welcome to Delphi; AChar:=Copy(AString,20,1); if AChar#0 then / #0是空字符,不是空格 begin if AChar! then Insert(AChar,AString,20); Exit; end; end; 在上述代碼中,雖然檢查了Copy()的返回值,但如果Copy()本
4、身調(diào)用失敗,則程序就執(zhí)行不到Exit語句。下面改用異常處理機(jī)制來編寫這段代碼。,var AChar,Astring:ShortString; begin try AString:=Welcome to Delphi; AChar:=Copy(Astring,20,1); if AChar! then Insert(AChar,AString,20); except Exit; end; End; 采用了異常處理機(jī)制后,可以先假設(shè)程序不可能出錯(cuò),按正常的順序編寫代碼。當(dāng)代碼在運(yùn)行過程中出現(xiàn)異常時(shí),將跳轉(zhuǎn)到except部分,執(zhí)行Exit語句。 異常處理機(jī)制有兩種結(jié)構(gòu):一種是tryexcept結(jié)構(gòu),
5、另一種是tryfinally結(jié)構(gòu),這兩種結(jié)構(gòu)在用法上有很大的區(qū)別。,7.1.2 錯(cuò)誤類型,一般來說,無論在編程的時(shí)候如何仔細(xì),程序總會(huì)有錯(cuò)誤。錯(cuò)誤分為4種類型:設(shè)計(jì)期錯(cuò)誤、編譯期錯(cuò)誤、運(yùn)行期錯(cuò)誤、邏輯錯(cuò)誤。 1. 設(shè)計(jì)期錯(cuò)誤 這種錯(cuò)誤類型發(fā)生在設(shè)計(jì)期,通常是因?yàn)榻o組件的某個(gè)屬性輸入了非法的值。例如,在設(shè)計(jì)數(shù)據(jù)庫應(yīng)用程序時(shí)指定了一個(gè)沒有定義的數(shù)據(jù)庫別名。 這種類型的錯(cuò)誤比較容易被發(fā)現(xiàn)和糾正,因?yàn)镈elphi能夠?qū)傩缘闹颠M(jìn)行合法性檢查。一旦發(fā)現(xiàn)這種錯(cuò)誤,Delphi將彈出一個(gè)警告窗口,提示用戶糾正錯(cuò)誤。,2. 編譯期錯(cuò)誤 編譯期錯(cuò)誤也叫語法錯(cuò)誤,當(dāng)程序代碼違反了Object Pascal的語法規(guī)
6、則時(shí)將發(fā)生這種錯(cuò)誤。 如果程序代碼中有語法錯(cuò)誤,編譯就不能通過,代碼編輯器的狀態(tài)欄將給出錯(cuò)誤信息提示,并在代碼編輯器中突出顯示有語法錯(cuò)誤的行。 比較常見的語法錯(cuò)誤是數(shù)據(jù)類型不匹配,特別是調(diào)用RTL、VCL或Windows的API時(shí)容易發(fā)生參數(shù)不匹配的錯(cuò)誤。為了避免這類錯(cuò)誤,建議使用Delphi的在線幫助,找到RTL、VCL或API的聲明,仔細(xì)對(duì)照它們的參數(shù)。不小心輸錯(cuò)變量名或命令語句拼寫錯(cuò)誤也是經(jīng)常造成編譯期錯(cuò)誤的原因。 編譯器檢查語法錯(cuò)誤的功能是可以自定義的??梢允褂谩綪roject】菜單中的【Options】命令打開【Project Options】對(duì)話框,然后設(shè)置編譯器的語法檢查選項(xiàng)。,
7、3. 運(yùn)行期錯(cuò)誤 程序雖然通過了編譯,但在運(yùn)行時(shí)失敗了,這種錯(cuò)誤稱為運(yùn)行期錯(cuò)誤。例如,程序試圖打開一個(gè)不存在的文件,或者在運(yùn)算時(shí)出現(xiàn)了被零除。 運(yùn)行期錯(cuò)誤分兩種情況,一種是運(yùn)行時(shí)隨運(yùn)行異常環(huán)境或用戶輸入的錯(cuò)誤參數(shù)而造成運(yùn)行錯(cuò)誤,這種情況的“錯(cuò)誤”往往無法在交付前通過調(diào)試排除,而通常由“異常處理”來解決;另一種是不隨環(huán)境和參數(shù)變化都會(huì)產(chǎn)生的運(yùn)行錯(cuò)誤,這種情況下,如果不能確認(rèn)錯(cuò)誤發(fā)生在什么地方,可以使用Delphi的內(nèi)部集成調(diào)試器幫助找到錯(cuò)誤所在。例如,可以通過單步執(zhí)行命令讓程序一條語句一條語句地執(zhí)行,或者通過一個(gè)觀察窗口來監(jiān)視某個(gè)變量的變化情況。,4. 邏輯錯(cuò)誤 邏輯錯(cuò)誤是指程序通過了編譯,也能
8、執(zhí)行,但執(zhí)行的結(jié)果與預(yù)期的不同。 邏輯錯(cuò)誤有時(shí)比較難找,因?yàn)榫幾g器無法識(shí)別這種錯(cuò)誤。此時(shí),需要用內(nèi)部集成調(diào)試器,通過控制程序的運(yùn)行以及監(jiān)視程序的輸出,來把錯(cuò)誤逐步定位在一個(gè)較小的范圍內(nèi)。 5. 怎樣盡可能地減少錯(cuò)誤 雖然錯(cuò)誤是很難避免的,但好的編程習(xí)慣能夠盡可能地減少錯(cuò)誤。以下是一些有關(guān)編程習(xí)慣的建議。 1) 程序應(yīng)盡可能地模塊化 程序分解為模塊后,由于每個(gè)模塊所要完成的任務(wù)相對(duì)簡單了,所以發(fā)生錯(cuò)誤的可能也就減少了。模塊化還簡化了程序的維護(hù)。,2) 養(yǎng)成良好的代碼書寫習(xí)慣 注釋能夠增加代碼的可讀性,方便維護(hù)和修改??s進(jìn)能夠使程序的語法結(jié)構(gòu)更加清晰。 3) 不要忘記檢查參數(shù)的值 在函數(shù)內(nèi)部,首先
9、要檢查傳遞過來的參數(shù)值是否合法,是否在一個(gè)可接受的范圍內(nèi)。 4) 不要忘記檢查函數(shù)的返回值 函數(shù)的返回值往往表示函數(shù)調(diào)用是否成功,以此決定下面的程序流程。如果貿(mào)然執(zhí)行下一步,有可能會(huì)出現(xiàn)意想不到的結(jié)果。,7.2 Delphi異常類,異常類是Delphi異常處理機(jī)制的核心,也是Delphi異常處理的主要特色。Delphi提供的所有異常類都是Exception類的子類。用戶也可以從Exception類派生一個(gè)自定義的異常類。Exception的一系列構(gòu)造函數(shù)中最重要的參數(shù)是顯示的錯(cuò)誤信息。而數(shù)據(jù)成員中最重要的也是可被引用的消息字符串(message,messagePtr)。從大的方面可以把異常類分
10、為運(yùn)行庫異常、對(duì)象異常、組件異常3類。 1. 整數(shù)異常 整數(shù)異常都是從一個(gè)EIntError類派生的,但程序運(yùn)行中引發(fā)的總是它的子類:EDivByZero、ERangeError和EIntOverFlow,見表7-1。,表7-1 整數(shù)異常及其產(chǎn)生原因,當(dāng)一個(gè)整數(shù)表達(dá)式的值超過為一個(gè)特定整數(shù)類型分配的范圍時(shí)引發(fā)ERangeError異常。比如下面一段代碼將引發(fā)一個(gè)ERangeError異常。 var SmallNumber:ShortInt; X,Y:Integer; begin X:=100; Y:=75; SmallNumber:=X*Y; end;,特定整數(shù)類型包括ShortInt、Byt
11、e以及與整數(shù)兼容的枚舉類型、布爾類型等,例如 : type THazard=(Safety,Marginal,Critical,Catastrophic); var Haz:THazard; Item:Integer; begin Item:=5; Haz:=THazard(Item); end;,由于枚舉類型越界而引發(fā)一個(gè)ERangeError異常。數(shù)組下標(biāo)越界也會(huì)引發(fā)一個(gè)ERangeError異常,如: var Values:array1.10 of Integer; I:Integer; begin for I:=1 to 11 do ValuesI:=I; end; ERangeErr
12、or異常只有當(dāng)范圍檢查打開時(shí)才會(huì)引發(fā)。這可以在代碼中包含$R+編譯指示或設(shè)置IDE Option|Project的Range_Checking Option選擇框。注意,Delphi不對(duì)長字符串做范圍檢查。,EIntOverFlow異常類在Integer、Word、Longint 3種整數(shù)類型越界時(shí)引發(fā)。如下面的代碼將引發(fā)一個(gè)EIntOverFlow異常。 var I:Integer; a,b,c:Word; begin a:=10; b:=20; c:=1; for I:=0 to 100 do c:=a*b*c; end; EIntOverFlow異常類只有在編譯選擇框Option|Pro
13、ject|Over_Flow_Check Option選中時(shí)才產(chǎn)生。當(dāng)關(guān)閉溢出檢查,則溢出后變量的值是丟棄溢出部分后的剩余值。,2. 浮點(diǎn)異常 浮點(diǎn)異常是在進(jìn)行實(shí)數(shù)操作時(shí)產(chǎn)生的,它們都從一個(gè)EMathError類派生,但與整數(shù)異常相同,程序運(yùn)行中引發(fā)的總是它的子類EInvalidOp、EZeroDivide、EOverFlow、EUnderFlow,見表7-2。 EInvalidOp最常見的引發(fā)條件是沒有協(xié)處理器的機(jī)器遇到一個(gè)協(xié)處理器指令。由于在默認(rèn)情況下Delphi總是把浮點(diǎn)運(yùn)算編譯為協(xié)處理器指令,因而在386以下微機(jī)上常常會(huì)碰到這個(gè)錯(cuò)誤。此時(shí)只需要在單元的接口部分設(shè)置全局編譯指示$N-,選
14、擇利用運(yùn)行庫進(jìn)行浮點(diǎn)運(yùn)算,問題就可以解決了。,表7-2 浮點(diǎn)異常類及其引發(fā)條件,各種類型的浮點(diǎn)數(shù)(Real、Single、Double、Extended)越界引起同樣的溢出異常。 4. 類型匹配異常 當(dāng)試圖用As操作符把一個(gè)對(duì)象與另一類對(duì)象匹配失敗后引發(fā)類型匹配異常EInvalidCast。,5. 類型轉(zhuǎn)換異常 當(dāng)試圖用轉(zhuǎn)換函數(shù)把數(shù)據(jù)從一種形式轉(zhuǎn)換為另一種形式時(shí)引發(fā)類型轉(zhuǎn)換異常EConvertError,特別是當(dāng)把一個(gè)字符串轉(zhuǎn)換為數(shù)值時(shí)引發(fā)。下面程序中的兩條執(zhí)行語句都將引發(fā)一個(gè)EConvertError異常。 var r1:Real; int:Integer; begin r1:=StrToF
15、loat($140.48); int:=StrToInt(1,402); end; 要注意,并不是所有的類型轉(zhuǎn)換函數(shù)都會(huì)引發(fā)EConvertError異常。比如當(dāng)函數(shù)Val無法完成字符串到數(shù)值的轉(zhuǎn)換時(shí)只有返回錯(cuò)誤代碼。利用這一點(diǎn)我們實(shí)現(xiàn)了輸入的類型和范圍檢查。,7.3 Delphi異常處理機(jī)制,Delphi異常處理機(jī)制建立在保護(hù)塊(Protected Blocks)的概念上。所謂保護(hù)塊是用保留字try和end封裝的一段代碼。保護(hù)塊的作用是當(dāng)應(yīng)用程序發(fā)生錯(cuò)誤時(shí)自動(dòng)創(chuàng)建一個(gè)相應(yīng)的異常類(Exception)。程序可以捕獲并處理這個(gè)異常類,以確保程序的正常結(jié)束以及資源的釋放和數(shù)據(jù)不受破壞。如果程序不
16、進(jìn)行處理,則系統(tǒng)會(huì)自動(dòng)提供一個(gè)消息框。,7.3.1 異常響應(yīng)與tryexcept語句,異常響應(yīng)為開發(fā)者提供了一個(gè)按自己的需要進(jìn)行異常處理的機(jī)制。tryexceptend形成了一個(gè)異常響應(yīng)保護(hù)塊。正常情況下except后面的語句并不被執(zhí)行,而當(dāng)異常發(fā)生時(shí),程序自動(dòng)跳到except,進(jìn)入異常響應(yīng)處理模塊。當(dāng)異常被響應(yīng)后異常類自動(dòng)清除。 tryexcept語句的一般格式如下: try /try保護(hù)代碼塊 被保護(hù)語句 except /異常處理塊 異常處理語句 /異常不發(fā)生,不處理 end; 或,try /try保護(hù)代碼塊 被保護(hù)語句 except /異常處理塊 on do /捕獲指定類型的異常對(duì)象,進(jìn)
17、行處理 on do /捕獲指定類型的異常對(duì)象,進(jìn)行處理 else /默認(rèn)的異常處理代碼 end; try語句塊指出了需要進(jìn)行異常保護(hù)的代碼。如果在這部分有不正常的事件發(fā)生,則引發(fā)一個(gè)異常對(duì)象。except是異常處理部分,被保護(hù)部分引發(fā)的異常對(duì)象將執(zhí)行或由這部分代碼捕獲并進(jìn)行處理。,【例7.1】 用tryexcept語句處理被0除的情況。 procedure TForm1.Button1Click(Sender: TObject); var a,b,c:real; begin b:=strtofloat(edit1.Text); c:=strtofloat(edit2.Text); try a:
18、=b /c; edit3.Text:=floattostr(a); except edit3.Text:=不能用0除; end; end;,在正常情況下(即由try保護(hù)的部分沒有異常事件發(fā)生時(shí)),應(yīng)用程序執(zhí)行完try部分代碼后,跳過except部分代碼,繼續(xù)運(yùn)行應(yīng)用程序。在執(zhí)行時(shí)內(nèi)代碼出現(xiàn)異常情況時(shí),引發(fā)一個(gè)異常對(duì)象后,應(yīng)用程序?qū)⑻^剩余的被保護(hù)部分未執(zhí)行的代碼,直接進(jìn)入except部分進(jìn)行異常處理,在except異常處理塊中,由try保護(hù)塊引發(fā)的異常對(duì)象也可以由以下語句來捕獲: on do 【例7.2】 兩數(shù)相除過程中發(fā)生異常時(shí)的處理情況如下。,procedure TForm1.Button
19、1Click(Sender: TObject); var a,b,c:real; begin try b:=strtofloat(edit1.Text); c:=strtofloat(edit2.Text); a:=b /c; edit3.Text:=floattostr(a); except on Ezerodivide do edit3.Text:=不能用0除; on EMathError do edit3.Text:=計(jì)算錯(cuò)誤; else edit3.Text:=發(fā)生異常; end; end;,保留字ondo用于判斷異常類型。這樣,可根據(jù)不同的異常類型,執(zhí)行不同的異常處理命令。如上例中,
20、在edit2中輸入0,則edit3中將顯示不能用0除;若在edit1和edit2同時(shí)輸入0,則edit3中將顯示計(jì)算錯(cuò)誤;若在edit1或edit2組件中輸入非數(shù)字字符,則edit3中將顯示發(fā)生異常。 注意:運(yùn)行時(shí)必須先編譯生成exe文件,然后在Windows中運(yùn)行,否則在發(fā)生異常時(shí)仍將出現(xiàn)系統(tǒng)的錯(cuò)誤信息。,7.3.2 異常保護(hù)與tryfinally語句,1. 需要保護(hù)的資源 一般說來需要保護(hù)的資源包括:文件、內(nèi)存、Windows資源和對(duì)象。 比如下面一段程序就會(huì)造成1KB的內(nèi)存資源的丟失。 var pPointer:Pointer; iInt,iDiv:Integer; begin iDiv
21、:=0; GetMem(pPointer,1024); /分配1KB的內(nèi)存 iInt:=10 div iDiv; /這里將觸發(fā)被零除的異常 FreeMem(pPointer,1024); /永遠(yuǎn)執(zhí)行不到這里 end; 由于程序從異常發(fā)生點(diǎn)退出,因而FreeMem永遠(yuǎn)沒有被執(zhí)行的機(jī)會(huì)。,2. 創(chuàng)建一個(gè)資源保護(hù)塊 在應(yīng)用程序運(yùn)行中產(chǎn)生了不正常的事件,要保證系統(tǒng)資源的釋放和關(guān)閉。 tryfinally語句的一般格式如下: try /try保護(hù)代碼塊 被保護(hù)語句 finally /異常處理塊 異常處理語句 /無論異常發(fā)生否,都必須處理 end 若把tryfinally語句用做創(chuàng)建一個(gè)資源保護(hù)塊時(shí),它的
22、格式可寫成: (分配系統(tǒng)資源) try (使用系統(tǒng)資源的語句) finally (釋放系統(tǒng)資源) end;,try前面的語句中包含了申請(qǐng)或創(chuàng)建系統(tǒng)資源的語句。try部分包含了使用系統(tǒng)資源的代碼語句。finally部分包含資源釋放語句。在應(yīng)用程序運(yùn)行過程中,如果在try部分產(chǎn)生異常情況,將直接跳過隨后的代碼,直接執(zhí)行finally部分的資源釋放語句。如果不產(chǎn)生異常,則應(yīng)用程序正常運(yùn)行,最后執(zhí)行finally部分中的資源釋放語句。 注意:在tryfinally語句中,當(dāng)try部分產(chǎn)生異常后,應(yīng)用程序直接執(zhí)行finally部分的資源釋放語句。 【例7.3】 用tryfinally語句確保所分配內(nèi)存資
23、源的在異常情況下仍被釋放。,var pPointer: Pointer; iInt,iDiv: Integer; begin iDiv:=0; GetMem(pPointer,1024); /分配1KB的內(nèi)存 try iInt:=10 div iDiv; /這將觸發(fā)異常 finally FreeMem(pPointer,1024);/釋放先前分配的內(nèi)存 end; end;,tryfinally結(jié)構(gòu)與tryexcept結(jié)構(gòu)在用法上主要有以下區(qū)別。 (1) 對(duì)于tryfinally結(jié)構(gòu)來說,不管try部分的代碼是否觸發(fā)異常,finally部分總是執(zhí)行的。如果發(fā)生異常,就提前跳到finally部分。
24、而對(duì)于tryexcept結(jié)構(gòu)來說,只有當(dāng)觸發(fā)了異常后,才會(huì)執(zhí)行except部分的代碼。 (2) 在tryexcept結(jié)構(gòu)中,當(dāng)異常被處理后異常對(duì)象就被釋放,除非重新觸發(fā)異常。而在tryfinally結(jié)構(gòu)中,即使finally部分對(duì)異常作了處理,異常對(duì)象仍然存在。 (3) finally部分不能處理特定的異常,因?yàn)樗鼪]有tryexcept結(jié)構(gòu)中的異常句柄,無法知道確切的異常類型。因此,在finally部分只能對(duì)異常做籠統(tǒng)的處理。 (4) 在tryfinally結(jié)構(gòu)中,如果在try部分調(diào)用標(biāo)準(zhǔn)命令Exit、Break或Continue,將導(dǎo)致程序的執(zhí)行流程提前跳到finally部分。finally
25、部分不允許調(diào)用上述3個(gè)命令。,7.3.3 異常的重引發(fā)和處理嵌套,由于異常在處理后即被清除,因而當(dāng)希望對(duì)異常進(jìn)行多次處理時(shí)就需要使用保留字raise 來重新引發(fā)一個(gè)當(dāng)前異常。 【例7.4】 同時(shí)使用異常響應(yīng)和異常保護(hù)來處理被0除和釋放資源,當(dāng)異常響應(yīng)結(jié)束時(shí)利用raise重新引發(fā)一個(gè)當(dāng)前異常。 var pPointer:Pointer; iInt,iDiv:Integer;,begin iDiv:=0; GetMem(pPointer,1024); try try iInt:=10 div iDiv; except On EDivByZero do begin iInt:=0; raise; e
26、nd; end; finally FreeMem(pPointer,1024); End; End;,7.3.4 定義自己的異常,使用自定義異常需要自己定義一個(gè)異常對(duì)象類和引發(fā)一個(gè)異常。 1. 定義異常對(duì)象類 異常是對(duì)象,所以定義一類新的異常同定義一個(gè)新的對(duì)象類型并無太大區(qū)別。由于默認(rèn)異常處理只處理從Exception或Exception子類繼承的對(duì)象,因而自定義異常類應(yīng)該作為Exception或其他標(biāo)準(zhǔn)異常類的子類。這樣,假如在一個(gè)模塊中引發(fā)了一個(gè)新定義的異常,而這個(gè)模塊并沒有包含對(duì)應(yīng)的異常響應(yīng),則默認(rèn)異常處理機(jī)制將響應(yīng)該異常,顯示一個(gè)包含異常類名稱和錯(cuò)誤信息的消息框。 下面是一個(gè)異常類的定
27、義。 type EMyException=Class(Exception);,2. 自引發(fā)異常 引發(fā)一個(gè)異常需要調(diào)用保留字raise,后邊跟一個(gè)異常類的實(shí)例。假如定義: type EPasswordInvalid=Class(Exception); 則在程序中如下的語句將引發(fā)一個(gè)EPasswordInvalid異常。 If PasswordCorrectPassword then raise EPasswordInvalid.Create(Incorrect Password entered); 異常產(chǎn)生時(shí)把System庫單元中定義的變量ErrorAddr的值置為應(yīng)用程序產(chǎn)生異常處的地址。在異
28、常處理過程中可以引用ErrorAddr的值。 在自己引發(fā)一個(gè)異常時(shí),同樣可以為ErrorAddr分配一個(gè)值。 為異常分配一個(gè)錯(cuò)誤地址需要使用保留字at,其使用格式如下: raise EInstance at Address_Expession;,【例7.5】 編寫一個(gè)利用自定義異常編程的完整實(shí)例。程序設(shè)計(jì)界面如圖7.1所示。 1) 新建應(yīng)用程序 啟動(dòng)Delphi,從【File】菜單中選取【New Application】命令,開始一個(gè)新的應(yīng)用文件,應(yīng)用程序中將有一個(gè)默認(rèn)窗體Form1。 2) 設(shè)置窗體屬性 將窗體Form1的Caption屬性設(shè)置為“自定義異?!保籉ont屬性設(shè)置為宋體、五號(hào);
29、Height和Width屬性分別設(shè)置為200、290。,3) 添加組件 向窗體Form1中添加兩個(gè)Label組件Label1和Label2,兩個(gè)Edit組件PassWord和InputEdit,兩個(gè)Button組件Button1和Button2。 4) 設(shè)置組件屬性 詳見表7-3。,圖7.1 自定義異常實(shí)例,表7-3 實(shí)例7.5組件屬性,窗體的布置如圖7.1所示。 程序啟動(dòng)時(shí)Label2、InputEdit不可見。當(dāng)在PassWord中輸入正確的口令時(shí),Label2、InputBox出現(xiàn)在屏幕上。此時(shí)Labell、PassWord隱藏。通過設(shè)置PassWord的PassWordChar為“*”
30、,可以使輸入口令時(shí)回顯在屏幕上的字符為“*”。,5) 自定義異常 自定義異常EInvalidPassWord和EInvalidInput分別用于表示輸入的口令非法和數(shù)字非法。它們都是自定義異常EInValidation的子類。而EInValidation直接從Exception異常類派生。 下面是3個(gè)異常類的定義: type TForm1 = class(TForm) private Private declarations public Public declarations end;,EInValidation=class(Exception) public ErrorCode:Integ
31、er; constructor Create(Const Msg:String;ErrorNum:Integer); end; EInvalidPassWord=class(EInValidation) public constructor Create; end; EInvalidInput=class(EInValidation) public constructor Create(ErrorNum:Integer); end;,EInValidation增加了一個(gè)公有成員ErrorCode來保存錯(cuò)誤代碼。錯(cuò)誤代碼的增加提供了很大的編程靈活性。對(duì)于異常類,可以根據(jù)錯(cuò)誤代碼提供不同的錯(cuò)誤信息
32、。對(duì)于使用者可以通過截取錯(cuò)誤代碼,在tryexcept模塊之外來處理異常。 從以上定義可以發(fā)現(xiàn):EInvalidPassWord和EInvalidInput的構(gòu)造函數(shù)參數(shù)表中沒有表示錯(cuò)誤信息的參數(shù)。事實(shí)上,它們保存在構(gòu)造函數(shù)內(nèi)部。下面是3個(gè)自定義異常類構(gòu)造函數(shù)的實(shí)現(xiàn)代碼。,constructor EInValidation.Create(Const Msg:String;ErrorNum:Integer); begin inherited Create(Msg); ErrorCode:=ErrorNum; end; constructor EInValidPassWord.Create; be
33、gin inherited Create(輸入的密碼不正確,0); end;,constructor EInValidInput.Create(ErrorNum:Integer); var Msg:String; begin case ErrorNum of 1: Msg:=無法把字符轉(zhuǎn)換成數(shù)字; 2: Msg:=數(shù)值超出范圍; else Msg:=輸入有錯(cuò); end; inherited Create(Msg,ErrorNum); end; 對(duì)于EInvalidInput,ErrorCode=1表示輸入的不是純數(shù)字序列,而ErrorCode=2表示輸入數(shù)值越界。,6) 添加事件 為窗體For
34、m1中的PassWord和InputEdit編輯框添加OnKeyPress事件,事件響應(yīng)過程分別為PassWordKeyPress和InputEditKeyPress。 7) 編寫事件代碼 口令檢查是用戶在PassWord中輸入口令并按下回車鍵后開始的。即在PassWordKeyPress中,要對(duì)口令進(jìn)行核對(duì)操作,若不正確,將觸發(fā)異常EInvalidPassWord。,procedure TForm1.PassWordKeyPress(Sender: TObject; var Key: Char); const CurrentPassWord=Delphi; begin if Key=#13
35、then begin try if PassWord.textCurrentPassWord then raise EInvalidPassWord.Create; Label2.Visible:=True; InputEdit.Visible:=True; InputEdit.SetFocus; PassWord.Visible:=False; Label1.Visible:=False;,except on EInvalidPassWord do begin PassWord.text:=; raise; end; end; Key:=#0; end; end; 同樣,在InputEdit
36、的OnKeyPress事件處理過程中實(shí)現(xiàn)了輸入數(shù)字的合法性檢查:,procedure TForm1.InputEditKeyPress(Sender: TObject; var Key: Char); var Res:Real; Code:Integer; begin if Key=#13 then begin try val(InputEdit.text,Res,Code); if Code0 then raise EInValidInput.create(1); if (Res1) or (Res0) then raise EInValidInput.create(2); MessageD
37、lg(輸入正確,mtInformation,mbOk,0); Key:=#0;,except on E:EInValidInput do begin InputEdit.text:=; MessageDlg(E.Message,mtWarning,mbOk,0); end; end; end; end; 8) 保存程序 將窗體Form1的單元文件保存為“Unit07_5.pas”,將項(xiàng)目文件保存為“Project07_5.dpr”。,9) 運(yùn)行程序 必須先編譯生成Project07_5.exe文件,然后在Windows資源管理器中運(yùn)行Project07_5.exe。運(yùn)行時(shí),不同的輸入會(huì)觸發(fā)不同
38、的異常。 由于異常被響應(yīng)后即被清除,所以要顯示異常信息,需要另外的手段。在以上兩段程序中采用了兩種不同的方法:在口令合法性檢查中,利用異常重引發(fā)由系統(tǒng)進(jìn)行默認(rèn)響應(yīng);在輸入數(shù)字合法性檢查中,通過異常實(shí)例來獲取異常信息并由自己來顯示它。,7.3.5 利用異常響應(yīng)編程,利用異常處理機(jī)制不僅能使程序更加健壯,而且也提供了一種使程序更加簡捷、明了的途徑。事實(shí)上,使用自定義異常類就是一種利用異常響應(yīng)編程的方式。 比如為了防止零作除數(shù),可以在進(jìn)行除法運(yùn)算前使用ifthenelse語句。但如果有一系列這樣的語句,則繁瑣程度是令人難以忍受的。這時(shí)可能傾向于使用EDivByZero異常。例如,如下一段程序就遠(yuǎn)比用
39、ifthenelse語句實(shí)現(xiàn)簡捷明了。,function Calcu(x,y,z,a,b,c:Integer):Real; begin try Result:=x/a+y/b+z/c; except On EdivByZerod do Result:=0; end; end; 【例7.6】 在文件的打開與創(chuàng)建中可以利用異常響應(yīng)來實(shí)現(xiàn)文件的打開或創(chuàng)建。,Procedure TRecFileForm.OpenButtonClick(Sender:TObject); begin if OpenDialog1.Execute then FileName:=OpenDialog1.FileName el
40、se exit; AssignFile(MethodFile,Filename); try Reset(MethodFile); FileOpened:=True; except OnEInOutError do begin,try if FileExists(FileName)=False then begin ReWrite(MethodFile); FileOpened:=True; end else begin FileOpened:=False; MessageDlg(文件不能打開,mtWarning,mbOK,0); end; except On EInOutError do be
41、gin FileOpen:=False; MessageDlg(文件不能創(chuàng)建,mtWarning,mbOK,0); end; end;,end; end; if FileOpened=False then exit; Count:=FileSize(MethodFile); if Count0 then ChangeGrid; RecFileForm.Caption:=FormCaption+-+FileName; NewButton.Enabled:=False; OpenButtomEnabled:=False; CloseButton.Enabled:=True; end; 總之,利用異
42、常響應(yīng)編程的中心思想是雖然存在預(yù)防異常發(fā)生的確定方法,但卻對(duì)異常的產(chǎn)生并不進(jìn)行事先預(yù)防,而是進(jìn)行事后處理,并以此來簡化程序的邏輯結(jié)構(gòu)。,7.4 Delphi調(diào)試器,7.4.1 準(zhǔn)備調(diào)試 在調(diào)試程序之前,必須保證程序代碼已經(jīng)沒有語法錯(cuò)誤,還要正確設(shè)置一些選項(xiàng)。為此,需要使用【Project】菜單中的【Options】命令打開【Project Options】對(duì)話框。打開 【Compiler】對(duì)話框,選中【Debug information】復(fù)選框(默認(rèn)為選中)。這樣,編譯器將把所有的調(diào)試信息加到.dcu文件和.exe文件中。 VCL的代碼都是仔細(xì)調(diào)試過的,一般不會(huì)有錯(cuò)誤。如果仍然不放心,想跟蹤進(jìn)
43、入VCL的內(nèi)部,則需要選中【Use Debug DCUs】復(fù)選框。 要說明的是,調(diào)試信息將使可執(zhí)行文件增大,但不影響程序的性能和對(duì)內(nèi)存的需求。盡管如此,調(diào)試結(jié)束后,最好要打開【Project Options】對(duì)話框,在【Compiler】選項(xiàng)卡中,清除【Debug information】復(fù)選框,再重新編譯程序。這樣,程序中就不包含任何調(diào)試信息。,要使用內(nèi)部集成調(diào)試器來調(diào)試程序,還必須使用【Tools】菜單中的【Debugger Options】命令打開【Debugger Options】對(duì)話框,選中【Integrated debugging】復(fù)選框(默認(rèn)為選中)。否則,【Run】菜單中的調(diào)試
44、命令將變灰。但要說明的是,內(nèi)部集成的調(diào)試器可能會(huì)與某些軟件沖突,從而引起應(yīng)用程序運(yùn)行異常。因此,在調(diào)試程序時(shí)最好把可能引起沖突的軟件退出運(yùn)行。 使用【Tools】菜單上的【Environment Options】命令打開【Environment Options】對(duì)話框,再打開【Preferences】選項(xiàng)卡。如果選中【Hide designers on run】復(fù)選框,當(dāng)程序運(yùn)行時(shí),【Object Inspector】和【Form】設(shè)計(jì)器將關(guān)閉,以騰出屏幕上的空間。如果選中【Minimize on run】復(fù)選框,當(dāng)程序運(yùn)行時(shí),IDE將最小化,以避免屏幕上內(nèi)容太多太亂。不過,當(dāng)程序暫停運(yùn)行時(shí),
45、IDE的窗口會(huì)重新恢復(fù)成原始大小。,7.4.2 設(shè)置調(diào)試器的選項(xiàng),1. 設(shè)置調(diào)試器選項(xiàng) 要設(shè)置調(diào)試器的選項(xiàng),可以使用【Tools】菜單中的【Debugger Options】命令打開【Debugger Options】對(duì)話框,如圖7.2所示。在其中的【General】選項(xiàng)卡、【Event Log】選項(xiàng)卡、【Language Exceptions】選項(xiàng)卡和【OS Exceptions】選項(xiàng)卡中,可以設(shè)置調(diào)試的一些環(huán)境、配置及方法等。,圖7.2 【Debugger Options】對(duì)話框,2. 編譯指令 默認(rèn)情況下,上述設(shè)置對(duì)整個(gè)項(xiàng)目的所有單元都有效。不過,也可以讓這些設(shè)置只對(duì)部分單元有效,因?yàn)橛?/p>
46、些單元可能沒有問題,不需要調(diào)試。 要使某個(gè)單元不包含調(diào)試信息,就在這些單元中加入適當(dāng)?shù)木幾g指令,例如: unit Unit1; $DEBUGINFO OFF interface 3. 自定義調(diào)試器的顏色 在前面已提到,代碼編輯器可以用不同的顏色顯示不同的語法成分,在使用調(diào)試器調(diào)試程序時(shí)也有這個(gè)功能。例如,通常斷點(diǎn)用白底紅色表示,當(dāng)前執(zhí)行點(diǎn)用白底藍(lán)色表示。 要自定義調(diào)試器的顏色,可以使用【Tools】菜單上的【Editor Options】命令打開【Editor Properties】對(duì)話框,再打開【Colors】選項(xiàng)卡,在【Element】框中選擇某種語法元素,然后設(shè)置它的前景顏色和背景顏色。
47、,7.5 控制程序的運(yùn)行,當(dāng)調(diào)試信息編譯了程序后,就可以調(diào)試程序了,調(diào)試器將接管對(duì)程序運(yùn)行的控制,但程序的運(yùn)行結(jié)果與在非調(diào)試狀態(tài)下運(yùn)行沒有什么兩樣,包括建立窗口、接受用戶輸入、計(jì)算數(shù)值、響應(yīng)事件、訪問數(shù)據(jù)庫等均照常進(jìn)行。,7.5.1 單步執(zhí)行,通過【Run】菜單中的【Step Over】命令,可以單步執(zhí)行程序。所謂單步執(zhí)行,就是一次只執(zhí)行一行(一個(gè)指令),這樣就可以知道哪一行或指令引起了運(yùn)行期錯(cuò)誤或邏輯錯(cuò)誤。 【Step Over】命令將把整個(gè)過程或函數(shù)當(dāng)做一行。如果把幾條語句寫在一行上,調(diào)試器將把這幾條語句當(dāng)做一條語句。這樣,就無法單獨(dú)調(diào)試其中的某一個(gè)語句。如果把一條長語句分成幾行寫,調(diào)試器
48、仍然把這幾行當(dāng)做一行。 調(diào)試器每執(zhí)行一行,當(dāng)前執(zhí)行點(diǎn)就自動(dòng)移到下一個(gè)要執(zhí)行的行上,但不一定是源代碼的下一行。例如,若正在執(zhí)行的是goto語句,當(dāng)前執(zhí)行點(diǎn)將移到goto語句跳轉(zhuǎn)到的行上。,另外還有一種情況就是,如果開啟了優(yōu)化編譯的選項(xiàng),某些源代碼行將被合并或越過,這時(shí)候,當(dāng)前執(zhí)行點(diǎn)不會(huì)移到這些行上。 為了清晰地看出當(dāng)前執(zhí)行點(diǎn)在哪兒,代碼編輯器將用白底藍(lán)色顯示當(dāng)前執(zhí)行點(diǎn),同時(shí),在“裝訂區(qū)”顯示一個(gè)綠色的箭頭指向當(dāng)前執(zhí)行點(diǎn),如圖7.3所示。 圖7.3 當(dāng)前執(zhí)行點(diǎn),7.5.2 跟蹤執(zhí)行,【Run】菜單中的【Trace Into】命令用于跟蹤程序。與單步執(zhí)行相似,這條命令一次也只執(zhí)行一行。不同的是,執(zhí)行
49、到有函數(shù)調(diào)用的行時(shí),這條命令將進(jìn)入函數(shù)的內(nèi)部。 如果程序鏈接了外部代碼諸如動(dòng)態(tài)鏈接庫,只要?jiǎng)討B(tài)鏈接庫包含了符號(hào)調(diào)試信息,就可以跟蹤進(jìn)入這些外部代碼。否則,調(diào)試器將把動(dòng)態(tài)鏈接庫當(dāng)做一行處理。 在調(diào)試過程中,可以根據(jù)需要交替使用單步執(zhí)行和跟蹤執(zhí)行。例如,對(duì)有疑問的調(diào)用命令使用跟蹤執(zhí)行,使控制進(jìn)入被調(diào)用部分內(nèi)部,調(diào)試該被調(diào)用部分。而對(duì)有把握的調(diào)用命令使用單步執(zhí)行,從而直接跳過被調(diào)用部分的調(diào)試,這樣能提高調(diào)試效率。,【Trace Into】命令也能夠進(jìn)入事件句柄的內(nèi)部,就像進(jìn)入一般的函數(shù)內(nèi)部一樣。要注意的是,OnPaint事件是當(dāng)應(yīng)用程序的窗口需要重畫的時(shí)候觸發(fā)的,當(dāng)進(jìn)入處理該事件的句柄內(nèi)部時(shí),代碼編
50、輯器的窗口將推到前端。也就是說,此時(shí)窗口需要重畫了,這樣又將觸發(fā)OnPaint事件。而一旦進(jìn)入處理OnPaint事件的句柄內(nèi)部,代碼編輯器的窗口又將被推到前端。如此反復(fù),構(gòu)成無限循環(huán)。要解決上述問題,必須把代碼編輯器與應(yīng)用程序的窗口在屏幕上重新排列,不要相互覆蓋。 程序往往大量調(diào)用了VCL的方法,一般情況下,不要跟蹤進(jìn)入VCL的內(nèi)部,因?yàn)閂CL的源代碼一般是不會(huì)出錯(cuò)的。如果懷疑VCL中可能出錯(cuò),或者想進(jìn)入VCL方法的內(nèi)部看看方法是怎樣實(shí)現(xiàn)的,也可以進(jìn)入VCL方法的內(nèi)部。Delphi Enterprise和Delphi Professional附帶了VCL的源代碼,而且還提供了帶調(diào)試信息的VCL
51、庫。,7.5.3 跳過一段代碼,為了節(jié)省時(shí)間和提高工作效率,不必每次都從頭開始單步或跟蹤執(zhí)行程序,可以直接跳到有疑問的地方,然后再一行一行地執(zhí)行程序。 【Run】菜單中的【Run to Cursor】命令可以實(shí)現(xiàn)這個(gè)功能。它能夠先以非調(diào)試方式執(zhí)行到光標(biāo)所在的行,再接管對(duì)程序的控制,單步或跟蹤執(zhí)行以后的代碼。 如果光標(biāo)所在的行不包含調(diào)試信息,調(diào)試器將彈出一個(gè)錯(cuò)誤框顯示“No code was generated for the current Line”。 如果不小心進(jìn)入了例程的內(nèi)部,想馬上退出來,可以把光標(biāo)移到該例程的最后一行,使用【Run to Cursor】命令,再使用【Step Over
52、】命令,就可以返回到調(diào)用該例程的地方。,7.5.4 全速執(zhí)行剩余的代碼,如果不小心進(jìn)入了一個(gè)例程,但又不想調(diào)試這個(gè)例程,或者確信該例程的代碼沒有問題,從而想盡快退出這個(gè)例程,可以使用【Run】菜單中的【Run Until Return】命令。這個(gè)命令將全速執(zhí)行該例程的代碼,直到返回為止。,7.5.5 返回到執(zhí)行點(diǎn),在調(diào)試過程中,隨時(shí)可以切換到IDE或其他程序中,進(jìn)行各種操作。 如果要重新回到調(diào)試器的當(dāng)前執(zhí)行點(diǎn),可以使用【Run】菜單中的【Show Execution Point】命令,光標(biāo)將自動(dòng)回到先前的執(zhí)行點(diǎn)上。 如果包含執(zhí)行點(diǎn)的源文件已關(guān)閉,調(diào)試器將重新打開這個(gè)源文件。如果執(zhí)行點(diǎn)沒有對(duì)應(yīng)的
53、源代碼,Delphi將打開CPU窗口,顯示相應(yīng)的機(jī)器指令。,7.5.6 暫停運(yùn)行,使用【Run】菜單中的【Program Pause】命令將使程序運(yùn)行暫時(shí)停止,這樣就可以檢查程序在此狀態(tài)下的輸出或變量的值是否正確,檢查完以后,可以繼續(xù)對(duì)程序進(jìn)行調(diào)試,或者修改變量的值再讓程序繼續(xù)執(zhí)行,以便看程序?qū)π碌闹禃?huì)做出什么反應(yīng)。 有時(shí)候,程序暫停后無法回到調(diào)試器中繼續(xù)運(yùn)行,這時(shí)候可以同時(shí)按下Ctrl+Alt+SysRq鍵終止程序的運(yùn)行,如果按一次無效,就多按幾次。,7.5.7 重新開始運(yùn)行,在調(diào)試過程中,可以使用【Run】菜單中的【Program Reset】命令中止程序的運(yùn)行并釋放所有占用的內(nèi)存和資源,
54、關(guān)閉所有打開的文件,清除所有的變量設(shè)置,然后重新運(yùn)行程序。這通常用于在調(diào)試過程中發(fā)現(xiàn)了錯(cuò)誤并更改了源代碼后需要重新編譯和運(yùn)行的情況。 【Program Reset】命令并不刪除先前設(shè)置的斷點(diǎn)和觀察表達(dá)式,因?yàn)橹匦麻_始調(diào)試程序時(shí)可能還要用到這些設(shè)置。 【Program Reset】命令可能不能很“干凈”地釋放應(yīng)用程序占用的所有資源,這樣可能導(dǎo)致其他程序運(yùn)行失敗,碰到這種情形應(yīng)當(dāng)退出Delphi或者重新啟動(dòng)Windows。,7.5.8 命令行參數(shù),如果要調(diào)試的程序需要傳遞參數(shù),可以使用【Run】菜單中的【Parameters】命令打開【Run Parameters】對(duì)話框,如圖7.4所示。 圖7.
55、4 命令行參數(shù) 在【Parameters】框內(nèi)鍵入要傳遞的參數(shù),也可以從以前鍵入過的參數(shù)中選擇一個(gè)。,7.6 斷 點(diǎn),所謂斷點(diǎn),就是在程序代碼的某一行上設(shè)置一個(gè)標(biāo)記,程序執(zhí)行到這里將暫停,由調(diào)試器接管對(duì)程序的控制。使用斷點(diǎn)與使用【Run to Cursor】命令有些相似,都是執(zhí)行到某一行后暫停。不同的是,程序中可以設(shè)置多個(gè)斷點(diǎn)并且能夠給斷點(diǎn)設(shè)置條件。 斷點(diǎn)通常設(shè)置在有疑點(diǎn)的區(qū)域。在遇到斷點(diǎn)之前,程序以全速運(yùn)行。遇到斷點(diǎn)之后,程序暫時(shí)停止運(yùn)行,以后就可以單步或跟蹤執(zhí)行程序。,7.6.1 源代碼斷點(diǎn),要在代碼編輯器中設(shè)置源代碼斷點(diǎn),有以下4種操作方式。 (1) 把光標(biāo)移到要設(shè)為斷點(diǎn)的行上,按下F5
56、鍵。 (2) 用鼠標(biāo)左鍵單擊要設(shè)為斷點(diǎn)的行的最左端。圖7.5 【Add Source Breakpoint】對(duì)話框 (3) 用鼠標(biāo)右鍵單擊要設(shè)為斷點(diǎn)的行,在彈出的菜單中選擇【Debug】命令,再選擇【Toggle Breakpoint】。 (4) 使用【Run】菜單中的【Add Breakpoint】命令,再選擇【Source Breakpoint】,Delphi將打開【Add Source Breakpoint】對(duì)話框,如圖7.5所示。,圖7.5 【Add Source Breakpoint】對(duì)話框,【Filename】框用于輸入斷點(diǎn)所在的源文件名(包含路徑)。 【Line number】框
57、用于輸入斷點(diǎn)所在的行號(hào)。 【Condition】框用于設(shè)置斷點(diǎn)有效的條件,通常是一個(gè)布爾表達(dá)式。布爾表達(dá)式中可以包含函數(shù)調(diào)用,只要該函數(shù)返回布爾值即可。 當(dāng)程序執(zhí)行到這個(gè)斷點(diǎn)時(shí),首先計(jì)算該布爾表達(dá)式的值。如果值為True,則斷點(diǎn)有效,程序?qū)和_\(yùn)行。如果值為False,則斷點(diǎn)無效,程序?qū)⒗^續(xù)執(zhí)行。,【Pass count】框用于指定經(jīng)過斷點(diǎn)多少次后斷點(diǎn)有效。例如,在一個(gè)For循環(huán)中設(shè)置一個(gè)斷點(diǎn),每次循環(huán)時(shí)都會(huì)遇到這個(gè)斷點(diǎn)。但并非每次遇到斷點(diǎn)時(shí)程序都會(huì)暫停,因?yàn)檫€需要經(jīng)過一定次數(shù)后斷點(diǎn)才有效。 【Group】框用于對(duì)斷點(diǎn)進(jìn)行分組。可以在這個(gè)框內(nèi)輸入一個(gè)新的組名,也可以選擇一個(gè)已有的組名。一旦若干
58、個(gè)斷點(diǎn)編成組,就可以分別使用【Disable Group】命令和【Enable Group】命令成組地被禁止或允許它們,還可以給一組斷點(diǎn)指定一系列動(dòng)作。 注意:設(shè)為斷點(diǎn)的行必須是可執(zhí)行的代碼行。如果把斷點(diǎn)設(shè)在注釋行、空行、變量聲明的行上,調(diào)試器將認(rèn)為斷點(diǎn)無效。 默認(rèn)情況下,斷點(diǎn)所在的行用白底紅字顯示,并且在裝訂區(qū)有一個(gè)紅色的小圓圈。如圖7.6所示。,圖7.6 斷點(diǎn),當(dāng)鼠標(biāo)指向這個(gè)小圓圈時(shí),將彈出一個(gè)提示窗口,顯示斷點(diǎn)的條件和經(jīng)過次數(shù),7.6.2 機(jī)器指令斷點(diǎn),Delphi允許針對(duì)某個(gè)機(jī)器指令設(shè)斷點(diǎn)。當(dāng)程序執(zhí)行到這個(gè)指令時(shí),就會(huì)暫停(必須執(zhí)行到斷點(diǎn)處設(shè)置)。要設(shè)置機(jī)器指令斷點(diǎn),有下列幾種方式。
59、(1) 在CPU窗口中用鼠標(biāo)左鍵單擊某個(gè)指令的裝訂區(qū)。 (2) 在CPU窗口中選擇一個(gè)指令,然后按 F5鍵。 (3) 在CPU窗口中用鼠標(biāo)右鍵單擊某個(gè)指令,在彈出的菜單中選擇【Toggle breakpoint】命令。 (4) 使用【Run】菜單中的【Add Breakpoint】命令,再選擇【Address Breakpoint】,彈出【Add Address Breakpoint】對(duì)話框,如圖7.7所示。,圖7.7 【Add Address Breakpoint】對(duì)話框,【Address】框用于指定斷點(diǎn)(在這里是機(jī)器指令)的地址。 【Condition】框用于設(shè)置斷點(diǎn)有效的條件。 【Pass count】框用于指定經(jīng)過斷點(diǎn)多少次后斷點(diǎn)有效。 【Group】框用于把斷點(diǎn)進(jìn)行分組。 當(dāng)程序執(zhí)行到這條指令時(shí),就會(huì)暫停(如果滿足有
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 保健拔罐師變更管理評(píng)優(yōu)考核試卷含答案
- 空調(diào)器壓縮機(jī)裝配工風(fēng)險(xiǎn)評(píng)估競賽考核試卷含答案
- 工藝畫制作工崗前工作技能考核試卷含答案
- 道路貨運(yùn)汽車駕駛員崗前沖突解決考核試卷含答案
- 2025年絲絹紡織及精加工產(chǎn)品項(xiàng)目發(fā)展計(jì)劃
- 2025年閑置物品調(diào)劑回收項(xiàng)目發(fā)展計(jì)劃
- 班委培訓(xùn)職責(zé)
- 2026北京密云初三上學(xué)期期末英語試卷和答案
- 2026年視頻會(huì)議攝像頭項(xiàng)目項(xiàng)目建議書
- 2025年江蘇省宿遷市中考化學(xué)真題卷含答案解析
- 廣東省花都亞熱帶型巖溶地區(qū)地基處理與樁基礎(chǔ)施工技術(shù):難題破解與方案優(yōu)化
- 生鮮乳安全生產(chǎn)培訓(xùn)資料課件
- GB 4053.3-2025固定式金屬梯及平臺(tái)安全要求第3部分:工業(yè)防護(hù)欄桿及平臺(tái)
- 2026年《必背60題》高校專職輔導(dǎo)員高頻面試題包含詳細(xì)解答
- GB/T 15390-2005工程用焊接結(jié)構(gòu)彎板鏈、附件和鏈輪
- GA 1016-2012槍支(彈藥)庫室風(fēng)險(xiǎn)等級(jí)劃分與安全防范要求
- 學(xué)生傷害事故處理辦法及案例分析
- 安全管理人員紅頭任命文件
- 6.項(xiàng)目成員工作負(fù)荷統(tǒng)計(jì)表
- 砂漿拉伸粘結(jié)強(qiáng)度強(qiáng)度試驗(yàn)記錄和報(bào)告
- 220kv輸電線路工程施工組織設(shè)計(jì)
評(píng)論
0/150
提交評(píng)論