C 異常處理

2021-08-02 06:22:18 字數 4619 閱讀 5143

1. 為什麼要異常處理

►在設計各種軟體系統中,處理程式中的錯誤和其它反常行為是非常

困難的,比如伺服器上長期執行的網路服務程式將80%的**用於

實現錯誤檢測和錯誤處理。

►異常是指程式執行時出現的不正常。程式執行過程中可能會出現下列異常:

►(1)cpu異常。在計算過程中,出現除數為0的情況。

►(2)記憶體異常:

► 使用new或malloc申請動態記憶體但儲存空間不夠;

► 陣列下標越界;

► 使用野指標、迷途指標讀取記憶體。

►(3)裝置異常。

► 無法開啟檔案,或能夠開啟檔案但檔案有損壞,從而無法讀取資料;

► 正在讀取磁碟檔案時挪動了檔案或磁碟;

► 正在使用印表機但裝置被斷開;

► 正在使用的網路斷線或阻塞。

►(4)使用者資料異常。

► scanf輸入時資料格式或型別有錯誤;

► 正在處理的資料庫有錯誤;

► 程式假定的資料環境發生變化。

2. 程式的健壯性

►健壯性又稱為魯棒性,是指程式對於規範要求以外的特殊情況的處

理能力。

►健壯的程式對於規範操作以外的特殊情況能夠有合理的處理方式。

►健壯性有時也和容錯性、可移植性或正確性有交叉的地方。

►乙個程式可以從錯誤的環境中推斷出正確合理的內容,這是容錯性

度量的標準,但也可以認為這個程式是健壯的。

►乙個程式可以正確的執行在不同環境下,則認為程式的可移植性高,

也可以稱該程式在不同平台下是健壯的。

►乙個程式能夠檢測自己內部的設計或者編碼錯誤,並得到正確的執

行結果,這是程式的正確性標準,但也可以說程式有內部的保護機

制,是健壯的。

►程式的健壯性是在異常情況下系統生存的關鍵所在,電腦程式在

輸入錯誤、磁碟故障、網路過載或惡意攻擊的情況下能否不宕機

不崩潰,就是程式的健壯性。

3. 異常處理的方法

►(1)終止模型。在終止模型中,將假設錯誤非常關鍵,以至於程

序無法返回異常發生的地方繼續執行。一旦異常被丟擲,就表明錯

誤已經無法挽回,程式不能繼續執行了。

►(2)恢復模型。恢復模型是指異常處理程式的工作是修正錯誤,

然後重新嘗試調動出問題的過程。

4. 異常處理的機制

►丟擲異常(throw)、檢查異常(try塊)、捕獲異常(catch塊)

►基本原理:把需要檢測的程式放到try塊中,把異常處理的程式放到

catch中。如果執行乙個函式時出現異常,可以不在該函式中立即

處理,而是丟擲異常資訊,傳遞給它的上一級函式(呼叫函式),

它的上一級函式捕獲到這個資訊後再進行處理。如果上一級函式也

不處理,就逐級向上傳遞。如果傳遞到了最高一級(如main函式)

還不處理,最後只能異常終止程式的執行。

►c++異常處理的機制使異常與處理可以不由同乙個函式來完成。這

樣做的優點是使深層次的函式專注於問題求解,而不必承擔處理異

常的任務,減輕了深層次函式的負擔,而把處理異常的任務集中到

某一層級的函式中專門來解決。

1. 丟擲異常

►可以使用throw表示式丟擲異常,將異常拋擲給主調函式去處理。

►throw表示式的一般形式為:

►異常通常以類似於實參傳遞給函式的方式(由throw)丟擲和(被

catch)捕獲,throw表示式的型別決定了所丟擲的異常型別。

throw 表示式;
►由於c++是根據型別來區分不同的異常的,因此在丟擲異常時,

throw表示式的值沒有實際意義,而表示式的型別則非常重要。如

果程式中有多處要丟擲異常,應該用不同的表示式型別來相互區別。

if(test==0) throw test; //丟擲int型異常

if(test==1) throw

'a'; //丟擲char型異常

if(test==2) throw

333.23; //丟擲double型異常

►關於throw的說明:

►(1)執行throw的時候,不會執行跟在throw後面的語句,而是將

程式從throw轉移到匹配的catch,該catch可以是同一函式中的

catch,也可以在直接或間接呼叫發生異常函式的上一級函式中。

►(2)被丟擲的物件是乙個用throw表示式初始化的「異常物件」

。異 常物件由throw建立,並初始化為被丟擲的表示式副本。異常物件

將傳遞給對應的catch,並在異常處理完成後撤銷。因此異常物件

必須是可以複製的型別(具有複製建構函式)。

►(3)如果丟擲的是陣列,被丟擲的物件自動該轉換為指向該陣列

首元素的指標,如果丟擲的是乙個函式,函式被轉換為指向該函式

的指標。

►(4)如果丟擲乙個指標,該指標是乙個指向派生類物件的基類指

針,則那個物件將被分割,只丟擲基類的部分。

►(5)丟擲指向區域性物件的指標總是錯誤的,因為丟擲指標的時候,

必須確保進入異常處理程式時指標所指向的物件仍然存在。

7 ►2. 檢測捕獲異常

►檢測捕獲異常的一般形式為:

try

catch(異常說明符1)

catch(異常說明符1)

…… //更多的catch

►乙個try塊可以緊跟乙個或多個catch塊。在try中執行程式塊所丟擲

的異常,通常會被其中的乙個catch子句處理,一旦catch子句執行

結束,程式流程繼續執行緊隨最後乙個catch子句後面的語句。

►catch子句中的異常說明符是有乙個形參的形參列表,有三種形式:

►① catch(型別名) //catch只需要了解異常的型別

►② catch(型別名 形參名) //catch需要了解異常的型別之外的資訊

►③ catch(…) //捕獲所有異常

9

►因為不可能知道可能被丟擲的所有異常,這時使用catch(…)是非常

有效的。如果catch(…)與其他catch子句結合使用,那麼它必須是最

後乙個,否則任何跟在它後面的catch子句都得不到匹配檢測。

try

catch(int)

catch(point)

catch(…)

►3. 異常處理的執行過程

►(1)程式流程到達try塊,然後執行try塊內的程式塊。如果沒有引

起異常,那麼跟在try塊後的catch子句都不執行,程式從最後乙個

catch子句後面的語句繼續執行下去。

►(2)丟擲異常的時候,將暫停當前函式的執行,開始查詢匹配的

catch子句。

►(3)首先檢查throw是否在try內部,如果是,檢查catch子句,看

是否其中之一與丟擲物件相匹配。如果找到匹配的catch,就處理

異常;如果找不到,就退出當前函式並釋放區域性物件,然後繼續在

呼叫函式中查詢。

►(4)如果找到匹配的catch,就處理異常;如果找不到,則退出調

用函式,然後繼續在呼叫這個函式的函式中查詢。

►(5)沿著巢狀函式呼叫鏈繼續向上,直到為異常找到乙個catch子

句。只要找到能夠處理異常的catch子句,就進入該catch子句,並

在它的處理程式中繼續執行。當catch結束時,跳轉到該try塊的最

後乙個catch子句之後的語句繼續執行。

//【例47.1】異常處理舉例。

#include

using

namespace

std;

void fun(int test)

catch(int)

cout

<<"caller1呼叫正常結束"

} void caller2(int test) catch(double)catch(...)

cout

<<"caller2呼叫正常結束"

} int main()

4. 重拋異常

►在catch子句中,可以再次丟擲異常。例如:

►其中throw不加表示式,表示再次丟擲try塊中檢測到的異常表示式

(throw 「hello」)。
►重拋異常不能被try-catch捕獲,只能傳到上一級函式。

trycatch(const

char *)

其中throw不加表示式,表示再次丟擲try塊中檢測到的異常表示式

(throw 「hello」)。

►重拋異常不能被try-catch捕獲,只能傳到上一級函式。

C 異常處理

結構化異常 structured exception vs c 異常 c exception 大家都知道c 異常是c 語言的乙個特性,使用者可以使用throw的方式來丟擲異常,try catch 來捕獲異常。結構化異常是諸如,zero divided,access violations等異常,這些異...

c 異常處理

一 概述 c 自身有著非常強的糾錯能力,發展到如今,已經建立了比較完善的異常處理機制。c 的異常情況無非兩種,一種是語法錯誤,即程式中出現了錯誤的語句,函式,結構和類,致使編譯程式無法進行。另一種是執行時發生的錯誤,一般與演算法有關。關於語法錯誤,不必多說,寫 時心細一點就可以解決。c 編譯器的報錯...

C 異常處理

程式設計師常常忽視異常處理的重要性,這給他們自己的 造成相當大損害。本文將討論如何在c 中使用異常處理,並介紹在應用 中新增 片段以防止某些錯誤的一些簡單方法,這些錯誤可能導致程式異常終止。結構化異常處理 net框架提供一種標準的錯誤報告機制稱為結構化異常處理。這種機制依賴於應用中報告錯誤的異常。在...