c 異常機制

2021-10-03 14:40:35 字數 1759 閱讀 7182

本例中,依據score構造出來的物件型別為int,與catch(int score)匹配上,程式控制權轉交到catch的語句塊,進行異常處理**的執行。如果在本函式內與catch語句的型別匹配不成功,則在呼叫棧的外層函式繼續匹配,如此遞迴執行直到匹配上catch語句,或者直到main函式都沒匹配上而呼叫系統函式terminate()終止程式。

異常物件是一種特殊的物件,編譯器依據異常丟擲表示式複製構造異常物件,這要求丟擲異常表示式不能是乙個不完全型別(乙個型別在宣告之後定義之前為乙個不完全型別。不完全型別意味著該型別沒有完整的資料與操作描述),而且可以進行複製構造,這就要求異常丟擲表示式的複製建構函式(或移動建構函式)、析構函式不能是私有的;

異常物件不同於函式的區域性物件,區域性物件在函式呼叫結束後就被自動銷毀,而異常物件將駐留在所有可能被啟用的catch語句都能訪問到的記憶體空間中,也即上文所說的tib。當異常物件與catch語句成功匹配上後,在該catch語句的結束處被自動析構;

在函式中返回區域性變數的引用或指標幾乎肯定會造成錯誤,同樣的道理,在throw語句中丟擲區域性變數的指標或引用也幾乎是錯誤的行為。如果指標所指向的變數在執行catch語句時已經被銷毀,對指標進行解引用將發生意想不到的後果;

在catch塊中,如果在當前函式內無法解決異常,可以繼續向外層丟擲異常,讓外層catch異常處理塊接著處理。此時可以使用不帶表示式的throw語句將捕獲的異常重新丟擲;

棧展開:就是從異常拋出點一路向外層函式尋找匹配的catch語句的過程,尋找結束於某個匹配的catch語句或標準庫函式terminate;

異常機制的乙個合理的使用是在建構函式中。建構函式沒有返回值,所以應該使用異常機制來報告發生的問題。更重要的是,建構函式丟擲異常表明建構函式還沒有執行完,其對應的析構函式不會自動被呼叫,因此析構函式應該先析構所有已初始化的基物件,成員物件,再丟擲異常;

別讓異常逃離析構函式:c++不禁止析構函式向外界丟擲異常,但析構函式被期望不向外界函式丟擲異常。析構函式中向函式外丟擲異常,將直接呼叫terminator()系統函式終止程式。如果乙個析構函式內部丟擲了異常,就應該在析構函式的內部捕獲並處理該異常,不能讓異常被丟擲析構函式之外。可以如此處理:若析構函式丟擲異常,呼叫std::abort()來終止程式。在析構函式中catch捕獲異常並作處理。

異常處理機制的主要環節是執行期型別檢查。當丟擲乙個異常時,必須確定異常是不是從try塊中丟擲。異常處理機制為了完善異常和它的處理器之間的匹配,需要儲存每個異常物件的型別資訊以及catch語句的額外資訊。由於異常物件可以是任何型別(如使用者自定義型別),並且也可以是多型的,獲取其動態型別必須要使用執行時型別檢查(rtti),此外還需要執行期**資訊和關於每個函式的結構。

當異常拋出點所在函式無法解決異常時,異常物件沿著呼叫鏈被傳遞出去,程式的控制權也發生了轉移。轉移的過程中為了將異常物件的資訊攜帶到程式執行處(如對異常物件的複製構造或者catch引數的析構),在時間和空間上都要付出一定的代價,本身也有不安全性,特別是異常物件是個複雜的類的時候。

異常處理技術在不同平台以及編譯器下的實現方式都不同,但都會給程式增加額外的負擔,當異常處理被關閉時,額外的資料結構、查詢表、一些附加的**都不會被生成,正是因為如此,對於明確不丟擲異常的函式,我們需要使用noexcept進行宣告。

C 異常 異常機制

c 異常是丟程式執行過程中發生的異常情況 例如被0除 的一種響應。異常提供了將控制權從程式的乙個部分傳遞到另一部分的途徑。對異常的處理有3個組成部分 引發異常 使用處理程式捕獲異常 使用try塊。程式在出現問題時將引發異常。throw語句實際上是跳轉,即命令程式跳到另一條語句。throw關鍵字表示引...

C 異常機制

在c 中的函式呼叫中,是用棧來存放其中資料物件。表1.1 我們結合這張表,來簡單介紹函式的棧結構。其中每乙個函式在入棧的時候,編譯器會自動新增額外的資料結構,這裡的exception registration就是被額外新增進來的。對於這個結構體我們稍後解釋,首先來介紹函式的基本結構。從這張圖中可以清...

C 異常機制

一 簡單例項 異常是通過丟擲物件而引發的,丟擲物件的型別決定應該啟用那個處理 即catch中的語句 被處理 是呼叫鏈中與該丟擲物件型別匹配,並且離丟擲異常位置最近的那乙個 例如 void test int main catch string e t value void print void pus...