1. 程式人生 > >delphi異常捕獲try except語句 和 try finally語句用法

delphi異常捕獲try except語句 和 try finally語句用法

perror 方式 檢測 變量 debug 創建用戶 進行 範圍 需要

原文地址:delphi try except語句 和 try finally語句用法以及區別


  1. 一直寫程序都沒管他們,也盡量很少用,今天終於想把他給弄個明白,在網上找來,記下!
    主要是前面小部分,後面的是詳細說明(很啰嗦!)

    一、異常的來源
      在Delphi的應用程序中,下列的情況都比較有可能產生異常。  
      (1)文件處理  
      (2)內存分配  
      (3)Windows資源 
      (4)運行時創建對象和窗體  
      (5)硬件和操作系統沖突
       
      二、異常的處理
      (1)try…except…end;  
      在try體內的代碼發生異常時,系統將轉向except部分進行異常的處理。這是Delphi處理異常的最基本的方式之一。
      
      (2)try…finally…end;  
      這種異常處理結構一般用於保護Windows的資源分配等方面,它確保了無論try體內的代碼是否發生異常,都需要由系統進行最後的統一處理的一些Windows對象的正確處理。  
      和try…except…end不同,該結構的finally部分總被執行。
      
      (3)不存在try…except…finally…end結構來既處理異常,又保護資源分配的結構,但是,try…except…end結構允許嵌套到try…finally…end結構中,從而實現既處理異常,又保護資源的分配。
      
      三、異常的精確處理
      (1)定義一個異常。  
      在Delphi中,每個異常都是Exception[1]類的一個派生類[2]。因此,定義一個異常就是定義一個Exception類的派生類。  
      type EMyException = class(Exception);  
      當然,基類可以是Exception或者Exception的任何一個任何層次的派生類。
      
      (2)在程序中拋出一個異常。  
      根據不同的情況拋出異常是使用異常的最基本的模式。在Delphi中,由raise語句來實現。  
      【語法】raise 異常類.Create(‘異常的缺省說明’);
      
      (3)在try…except…end中更加精確的捕捉異常。  
      使用on E:異常類 do…結構可以在do體內處理特定異常類所拋出的異常。
      
      四、異常的調試
      在Delphi IDE中,解除“Debugger Options”(可以使用菜單Tools—>Debugger Options…進行訪問)中的Integrated Debugging復選框的勾選狀態可以進行異常的調試。
      
      五、異常的補充說明
      (1)每一段程序都有可能產生錯誤!這是軟件業的一個不容置疑的現象和規律。事實上,傳統的if…else…結構完全可以解決所有的錯誤,使用Exception機制也沒能夠回避在最原始的層次,通過遍歷可能的情況來產生異常的做法,那麽,為什麽還要異常機制?
      
      答案很清楚:異常提供了一種更加靈活和開放的方式,使得後來的編程者可以來根據實際的情況處理這種錯誤,而不是使用預先設定好的處理結果。

    Delphi7異常處理
    了解什麽是異常和Delphi7中提供的異常類
    掌握Delphi7環境下自定義異常的方法和異常
    處理的語法結構與實現

    異常

    什麽是異常
    程序開發過程中,有編譯期錯誤和運行期錯誤,編譯期錯誤很容易發現,而運行期錯誤(邏輯錯誤和異常)往往很難預料.為了程序的穩定性和可靠性,就需要對程序異常處理和保護.

    異常:理解為一種特殊的事件,該事件發生時,程序的正常執行將被打斷.
    由程序導致的不正常情況是錯誤而不是異常,程序錯誤與異常不是相同的概念.
    異常是為方便用戶報告錯誤並處理錯誤而創建的機制,一般是由操作系統完成的.
    運行期錯誤處理

    軟件開發過程中,程序員必須提供適度的方式來處理不可避免的錯誤.一般方法如下:
    1 傳統方法
    2 使用異常進行錯誤處理

    傳統方法
    在Pascal早期版本中,程序員必須借助編譯器開關和狀態變量去檢測和處理存在的錯誤.

    {$I-}{此編譯器指令關閉I/O檢測}
    Assign(InFile,InputName);
    Reset(InFile);
    {$I+}{此編譯器指令恢復I/O檢測}
    If IOResult0 then
    {錯誤處理代碼};

    使用異常進行錯誤處理

    結構化異常處理是Delphi語言內建的特性.為我們處理異常提供了方便.處理異常有兩方面:
    1 異常處理可確保適當地恢復在應用程序中分配或改變的任何資源.
    2 結構化異常處理為開發人員提供了一種一致的處理各種類型運行期錯誤的方式

    Delphi7異常處理機制

    異常處理的基本思想是通過提供規範方式處理軟,硬件錯誤的能力,使程序更加健壯.
    異常處理可以將處理錯誤的代碼與正常的邏輯處理代碼相分離.
    Delphi缺省的方式是在應用程序收到異常之前捕獲異常.IDE會給出一個”預警”對話框,以指明應用程序將要產生異常.
    異常處理機制是一種程序設計安全策略,它是建立在保護塊思想上,通過try和end語句塊對代碼的封裝確保在程序發生異常時,程序能夠正常運行或釋放所占用的資源.

    Delphi7異常處理機制

    傳統程序設計中,用如下的偽代碼方法來檢查和處理程序錯誤:

    執行一個任務
    If 前一個任務未能正確執行
    執行錯誤處理
    執行下一個任務
    If 前一個任務未能正確執行
    執行錯誤處理
    ……

    Delphi7異常處理機制
    例;

    try Age := StrToInt(Edit1.Text); ShowMessage(Format(‘生於%d年‘, [YearOf(Now) - Age])); except on               do showmessage(‘輸入編輯框的不是一個有效的數字!‘); on ERangeError do showmessage(‘輸入編輯框的年齡值太大!‘); end; 

    異常類
    Delphi7根據異常類型定義了相應的異常類.所有異常類的基類都是Exception類.
    Delphi7內置了大量的異常類,用戶也可以通過Exception類自定義異常類.

    記住異常類的要點:
    1 異常類是響應不同異常現象的入口.
    2 熟悉異常類的層次結構.

    Exception異常類

    Exception是所有異常類的基類,它並不是以’T‘開頭,而是以’E‘開頭,它的派生類也是以’E‘開頭的.
    Exception類定義於SysUtils單元中.
    Exception類最常用的方法是Create方法:
    Constructor Create(const Msg:string);
    Exception.Create(‘我自己創建的異常!’);
    該方法用於創建一個異常類的實例,也可以顯示錯誤信息,也可直接用這個方法提交一個異常
    raise Exception.Create(‘我拋出的異常!’);

    例:

    try raise Exception.Create(‘我拋出的異常!‘); except on E: Exception do showmessage(‘異常類名稱:‘ + E.ClassName + #13#10 + ‘異常信息:‘ + E.Message); end; 

    Delphi7內置的異常類
    Delphi7根據異常現象的類型定義了相應的異常類,這些異常類又稱為Delphi7內置的異常類.

    具體分為運行時庫異常類,對象異常類和組件異常類三大類.

    運行時庫異常類(RTL)
    運行時庫異常類可分為以下幾種:
    1 整數計算異常 2 浮點計算異常 3 硬件異常 4 堆異常 5 輸入輸出異常(I/O異常) 6 字符轉換異常 7 類型轉換異常 8 啞異常

    整數計算異常

    EIntError 整數計算異常(基類)
    EDivByZero 整數除0溢處
    EIntOverFlow 整數溢出
    ERangeError 整數越界

    浮點計算異常

    EMathError 浮點計算異常(基類)
    EInvalidOp 無效浮點操作指令
    Eoverflow 浮點操作上溢
    Eunderflow 浮點操作下溢
    EZeroDivide 浮點計算除0

    硬件異常

    EProcessorException 硬件異常(基類)
    ESingleStep 應用程序產生單步中斷
    Ebreakpoint 應用程序產生斷點中斷
    Efault 故障(繼承EProcessorException,也是基類)
    EStackFault 對處理器棧段的非法訪問
    EPageFault 內存管理器無法正確使用交換文件
    EGPFault 保護性錯誤,一般由未初始化指針或對象造成
    EInvalidOpCode 處理器遇到未定義指令

    堆異常和(I/O異常)
    堆異常:

    EOutOfMemory 堆中沒有足夠的內存完成操作
    EInvalidPointer 試圖訪問一個堆外的指針
    (I/O異常)
    EInOutError DOS輸入/輸出錯誤

    字符轉換/類型轉換異常和啞異常

    字符轉換異常
    EConvertError 數字到字符串或字符串到數
    字轉換錯誤

    類型轉換異常

    EInvalidCast 類型轉換異常

    啞異常

    EAbort 調用Abort產生,不顯示錯誤提示框

    對象異常類
    對象異常類是針對非組件對象引發的異常而定義的.
    對象異常類包括:

    1 流異常類
    2 打印異常類
    3 圖形異常類
    4 字符串鏈表異常類

    流異常類

    流異常是指在程序中進行與流相關的操作時產生的異常.流異常類的基類是EStreamError,其他流異常類都直接或間接從它派生.
    派生關系見書48頁圖

    打印異常

    打印異常是由於應用程序向不存在的打印機發送打印命令或由於某種原因打印工作無法送到打印機時引發的.
    打印異常類為Eprinter,定義於Printers單元

    圖形異常

    圖形異常主要包括EInvalidGraphic和
    EInvalidGraphicOperation兩個類均定義於Graphics單元

    EInvalidGraphic異常滿足下列情況之一時引發:

    當應用程序試圖向一個並不包含合法的位圖,圖象,元文件或用戶自定義圖形類型的文件中裝入圖象時.
    當應用程序試圖裝入不可識別擴展名的文件時
    當圖象與LoadFromClipboardFormat或SaveToClipboardFormat中的格式不匹配時.
    當應用程序試圖將圖象的PixelFormat設為不支持的值

    EInvalidGraphicOperation異常在滿足下列條件之一時發生:

    應用程序訪問圖象中不存在的掃描線時.
    應用程序不能成功寫入圖象時.
    應用程序在畫布未處於有效狀態時進行繪制.
    應用程序裝入未知或不支持的圖象格式時.
    應用程序將圖象的PixelFormat設為不支持的值時
    不能分配該操作的句柄時.

    字符串鏈表異常

    字符串鏈表異常是由於用戶對字符串鏈表進行非法操作時引發的.
    包括EStringListError,EListError等.由於許多部件都有一個Tstrings抽象類的屬性(如Tiistbox組件的Items屬性等),因而字符串鏈表異常在組件編程中很重要.

    EStringListError一般在字符串鏈表越界時產生.而EListError異常通常在以下情況下發生:

    當索引項超出鏈表範圍時
    當字符串鏈表的Duplicates屬性設置為dupError
    同時應用程序試圖加入一個重復的字符串時.
    當向已排序的字符串鏈表中插入字符串時.

    組件異常類

    組件異常類用於響應組件異常,組件異常是由於對VCL組件進行操作時,違反了組件的使用規則及其特征而引發的,可分為兩大類:
    通用組件異常、專用組件異常、通用組件異常。
    常見的有非法操作異常,組件異常和資源不足異常三種類型,對應於EInvalidOpetation,EComponentError和EOutOfResource異常類.

    引發非法操作異常的原因有:

    應用程序試圖對Parent屬性為nil的組件進行一些需要窗口句柄的操作.
    試圖對窗體拖放操作.

    引發組件異常的原因有:
    Delphi不能註冊某個組件

    應用程序不能重命名某個組件
    資源不足異常被引發是由於當應用程序試圖創建窗口句柄而操作系統沒有多余的句柄可分配

    專用組件異常:許多組件都定義了相應的組件異常類.

    列出幾個典型的組件異常類:

    EMenuError異常,菜單異常,是由於程序對菜單的非法操作而引發的.定義於Memus單元
    EInvalidGridOperation異常.非法的網格操作,如試圖引用一個不存在的網格單元時引發.定義於Grids單元
    EDatabaseError異常.數據庫異常是由於對數據庫的非法操作引起的.

    用戶自定義異常類

    創建用戶自定義異常類的方法

    拋出自定義異常
    用戶自定義異常類與內置異常類的區別
    異常類對象與其他類對象的區別
    創建用戶自定義異常類的方法

    選擇Exception作為基類,按照定義類的一般方法,建立自定義的異常類就可以了.
    如:

    type EMyException = class(Exception) //需要定義屬性或方法時,寫在此處即可 end; 

    拋出自定義異常
    Delphi不會管理用戶自定義異常的拋出,程序員必須自己拋出自己創建的異常.用raise語句可拋出異常:

    raise EMyException.Create(‘My Exception‘); 

    用戶自定義異常類與內置異常類的區別

    Delphi不會自動響應用戶自定義的異常類,所以用戶自定義的異常類需要使用raise語句拋出,而內置異常類與運行期真實的異常現象相對應,當異常發生時,操作系統會捕捉到此異常,通知Delphi去響應.

    異常類對象與其他類對象的區別

    異常類對象創建後,不需要由用戶釋放它,當異常處理之後,系統會自動調用析構函數釋放異常類對象.而其他類需要由用戶來釋放.

    Delphi7的異常處理結構

    try…finally 語句塊
    Try…except語句塊
    使用raise拋出異常

    try…finally 語句塊
    try…finally 語句塊是用於資源保護和恢復系統狀態,不管try部分的操作是否有異常發生,finally部分的操作都要進行.
    語法如下:

    try 被保護語句 finally 處理語句(無論異常是否發生,都必須處理) end; 

    try…finally 語句塊主要用於資源保護

    應用程序向系統申請了資源(如內存,圖形句柄),當不需要這些資源時,就應該及時釋放資源.
    句柄:系統資源是有限的,一般構成一個資源鏈,鏈的長度是有限的,當系統給應用程序分配資源時,給每個資源設置一個ID號,這個ID號就是句柄.(系統資源相當於一個個房間,而句柄就相當於房間號.)
    句柄有限:1 資源是有限的;2數字表達的範圍也是有限的(整數有範圍的)

    Try…except語句塊
    Try…except語句塊用於運行期錯誤處理,程序員可以用它編寫對不同類型異常的處理.
    異常發生後,判斷異常的類型,正確處理異常.

    Try…except語句塊一般和On…Do子句連用;
    語法如下:

    function Test(x, y: Real): Real; begin try Result := x / y;//被保護語句 except on EInvalidOp do Result := 0;//異常處理語句 on EZeroDivide do Result := 0; on EOverFlow do Result := 0; on EUnderFlow do Result := 0; end; end; 

    Try…except語句塊主要處理 缺省異常
    用戶一般只處理一些特殊的異常,並不是處理所有的異常.對那些用戶不關心的異常就可以采用缺省異常來處理.

    try //正常程序代碼 except on EExceptionClass do //處理特定類型的異常 else //缺省異常處理 end; 

    註:else塊必須位於except塊的最後,可響應任何類型的異常

    異常的傳遞

    Delphi對異常的處理方式是向後掃描程序的調用棧.假如過程A內有過程保護代碼塊,在此代碼塊內又調用了過程B,過程B沒有異常保護,過程B調用了過程C,在C內發生了異常.如C內有該異常的處理程序,那麽程序調用C的異常處理代碼

delphi異常捕獲try except語句 和 try finally語句用法