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框架提供一種標準的錯誤報告機制稱為結構化異常處理。這種機制依賴於應用中報告錯誤的異常。在...