c++ 異常處理

程序異常的概念

主要是指出現了一些很少發生或者出乎意料的狀態,通常顯示一個程序的錯誤或者要求一個必須迴應的。如果不能滿足這個迴應則會經常造成程序卡死不能進行相應的處理。

c語言裏面有幾個異常管理機制,這些標準在c++裏面也可以用,但是c++設計了更加方便的基本不可見處理方式。

使用try與catch塊就可以實現對程序異常的捕捉和處理,但是注意的是一定要保證所有的異常的類型和拋出異常類型的一致,不然就很難捕捉得到。在catch裏面添加需要捕捉的內容,之後在try裏面加入所有需要檢驗是否拋出異常的代碼。

絕對終止機制

這是一種徹底忽略異常的方法,使用一種安全的退出方法,在一些情形裏面是最正確的方法,c庫文件提供兩個不是相當完美的程序函數。abort還有exit這兩個函數都不是將程序交還給用戶處理而是字節中子程序交還給系統。

  • abort:這是默認的,在運行的時候診斷裏調用abort來安全結束程序,這種結束方式可能不會刷新與關閉打開的文件,或者刪除臨時文件愛你,與你的設計有關。
  • exit:附加了關閉打開的文件與返回狀態碼給執行環境,並且調用atexit註冊的返回函數

通常是很重大程序失敗會調用abort函數,原因abort默認行爲是立即結束程序,需要在調用abort之前保存數據。

對於exit函數執行的回調函數其實是按照註冊順序的逆序調用的

有條件的結束程序

可以使用斷言

assert函數,一般定義在assert.h文件裏面,在斷言函數裏面不能有實質性的動作,一般只是做些比較與判斷就好。否則調試和發佈版會有很大區別

非局部GOTO機制

setjmp和longjmp可以跨越函數,因爲共同是不可以跨越函數的,但是異常處理是可以跨越函數的。

異常申明

申明c++函數申明的一種,指定了函數可以拋出什麼異常

c++標準庫

裏面介紹的關於異常的部分的內容

error_code類裏面大致內容

namespace std{
   class error_code{
      public:
       const error_category& category() const noexcept;
       int value() const noexcept;
       string message() const noexcept;
       explicit operator bool() const noexcept;
       error_condtion default_error_condtion() const noexcept;
   };
}

noexcept修飾符的作用

noexcept形如其名地,表示其修飾的函數不會拋出異常。

在C++11中如果noexcept修飾的函數拋出了異常,編譯器可以選擇直接調用std::terminate()函數來終止程序的運行,這比基於異常機制的throw()在效率上會高一些。

這是因爲異常機制會帶來一些額外開銷,比如函數拋出異常,會導致函數棧被依次地展開(unwind),並依幀調用在本幀中已構造的自動變量的析構函數等

error_category類的內部結構(部分)

namespace std{
  class error_category{
     public:
       virtual const char * name() const noexcept;
       virtual string  message() const noexcept;
       virtual error_condition default_error_condition(int ev)
       bool operator==(const error_category& rts) const noexcept;
       bool operator!=(const error_category& rts) const noexcept;
           ...
  };
}

name函數:返回分類名稱

message函數:返回傳入值的響應信息

default_error_condition:默認的差錯狀態

使用方式

舉一個泛型函數來處理不同的異常

#include <exception>
#include <system_error>
#include <future>
#include <iostream>


std::exception_ptr eptr;

template <typename T>
void processCodeException (const T& e)
{
    using namespace std;
    auto c = e.code();
    cerr << "-category : " << e.category().name() << endl;
    cerr << "-value : " << e.value() < endl;
    cerr << "-msg : " << e.message() << endl;
    cerr << "-def category : " << e.default_error_condition().category().name() << endl;
    cerr << "-def mes : " << e.default_error_condition().message();
    cerr << "-def value : " << e.default_error_condition().value();
}

void processExecption()
{
    using namespace std;
    try{
        ...
    }
    catch(const system_error & e){
        cerr << "SYSTEM EXCEPTION :" << e.what() << endl;
        processCodeException(e);
        //或者也可以使用current_exception
        eptr = std::current_exception();
        //如果需要在某個場景重新拋出這個異常的話也可以使用rethrow_exception
        std::rethrow_exception(eptr);
    }
}

參考資料:

https://baijiahao.baidu.com/s?id=1611302717509096034&wfr=spider&for=pc

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章