C 異常處理

2021-10-10 12:35:47 字數 3562 閱讀 1990

c++異常處理

程式的錯誤大致可以分為三種,分別是語法錯誤、邏輯錯誤和執行時錯誤:

1) 語法錯誤在編譯和鏈結階段就能發現,語法錯誤是最容易發現、最容易定位、最容易排除的錯誤,例如關鍵字輸錯了、分號括號等需要在英文輸入法輸入的誤用中文輸入法輸入。

2) 邏輯錯誤是說我們編寫的**思路有問題,不能夠達到最終的目標,這種錯誤可以通過除錯來解決。

3) 執行時錯誤是指程式在執行期間發生的錯誤,如記憶體分配失敗、陣列越界、檔案不存在等。c++ 異常(exception)機制就是為解決執行時錯誤而引入的。

程式執行時常會碰到一些錯誤,這些錯誤如果不能發現並加以處理,很可能會導致程式崩潰。c++ 異常處理涉及到三個關鍵字:try、catch、throw。

c++ 異常處理機制提供了一種轉移程式控制權的方式。執行時錯誤如果放任不管,系統就會執行預設的操作,終止程式執行,也就是我們常說的程式崩潰(crash)。c++ 提供了異常機制,讓程式捕獲執行時錯誤,並處理這個問題,或者至少告訴使用者發生了什麼再終止程式。

可以借助 c++ 異常機制來捕獲上面的異常,避免程式崩潰。捕獲異常的語法為:

try 

catch(型別名 [形參名]) // 捕獲特定型別的異常 

catch(型別名 [形參名]) // 捕獲特定型別的異常 

catch(...)    // 三個點則表示捕獲所有型別的異常 

try區段:這個區段中包含了可能發生異常的**,在發生了異常之後,需要通過throw丟擲。

catch子句:每個catch子句都代表著一種異常的處理。catch子句用於處理特定型別的異常。

throw子句:throw 子句用於丟擲異常,被丟擲的異常可以是c++的內建型別(例如: throw int(1);),也可以是自定義型別。

異常的處理規則

☆throw丟擲的異常型別與catch抓取的異常型別要一致;

☆throw丟擲的異常型別可以是子類物件,catch可以是父類物件;

☆catch塊的引數推薦採用位址傳遞而不是值傳遞,不僅可以提高效率,還可以利用物件的多型性。另外,派生類的異常捕獲要放到父類異常撲獲的前面,否則,派生類的異常無法被撲獲;

☆如果使用catch引數中,使用基類捕獲派生類物件,一定要使用傳遞引用的方式,例如catch (exception &e);

☆異常是通過丟擲物件而引發的,該物件的型別決定了應該啟用哪個處理**;

☆被選中的處理**是呼叫鏈中與該物件型別匹配且離丟擲異常位置最近的那乙個;

☆在try的語句塊內宣告的變數在外部是不可以訪問的,即使是在catch子句內也不可以訪問;

☆棧展開會沿著巢狀函式的呼叫鏈不斷查詢,直到找到了已丟擲的異常匹配的catch子句。如果丟擲的異常一直沒有函式捕獲(catch),則會一直上傳到c++執行系統那裡,導致整個程式的終止。

c++ 標準異常

c++ 提供了一系列標準異常,定義在 中,我們可以在程式中使用這些標準的異常。它們是以父子類層次結構組織起來的,標準異常類的繼承關係如下圖所示:

表是對上面層次結構**現的每個異常的說明:

異常

描述

exception

該異常是所有標準 c++ 異常的父類。

bad_alloc

該異常可以通過new丟擲。

bad_cast

該異常可以通過dynamic_cast丟擲。

bad_exception

這在處理 c++ 程式中無法預期的異常時非常有用。

bad_typeid

該異常可以通過typeid丟擲。

logic_error

理論上可以通過讀取**來檢測到的異常。

domain_error

當使用了乙個無效的數學域時,會丟擲該異常。

invalid_argument

當使用了無效的引數時,會丟擲該異常。

length_error

當建立了太長的 string 時,會丟擲該異常。

out_of_range

該異常可以通過方法丟擲,如vector和bitset<>::operator()。

runtime_error

理論上不可以通過讀取**來檢測到的異常。

overflow_error

當發生數學上溢時,會丟擲該異常。

range_error

當嘗試儲存超出範圍的值時,會丟擲該異常。

underflow_error

當發生數學下溢時,會丟擲該異常。

例1、捕捉標準異常的例子

#include

using namespace std;

int main()

catch (exception &e)

return 0;

}執行之,參見下圖:

當使用new進行開空間時,申請記憶體失敗,系統就會丟擲異常,不用使用者自定義異常型別,此時捕獲到異常時,就可告訴使用者是**的錯誤,便於修改。

拋出自定義型別異常

雖然 c++ 加入了異常機制來處理很多執行時錯誤, 但是異常機制的功效非常受限, 很多錯誤還沒辦法用標準異常(原生異常)手段捕捉, 比如整數除 0 錯誤——c++標準沒有把除0錯當成標準異常。先看下面這段**:

#include

using namespace std;

int main()

執行之,參見下圖:

將上面的**改為:

#include

using namespace std;

int main()

catch (...)

return 0;

}執行之,參見下圖:

c++為什麼抓不到除0錯「異常」? 參見

什麼事也沒發生一樣,c++對除數為0沒有捕獲到,對於這種情況,怎麼辦?新增乙個判斷除數是否為0的條件,使用 throw 語句丟擲異常——拋出自定義型別異常。

例2、拋出自定義型別異常並捕捉的例子:

#include

using namespace std;

double division(float a, float b)

return (a/b);

}int main ()

catch (const char* msg)

return 0;

}執行之,參見下圖:

進一步理解可參見:c++異常捕捉與處理的深入講解

C 異常處理

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

c 異常處理

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

C 異常處理

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