異常處理總結(一)

來源:互聯網
上載者:User

      對於初學軟體開發的人來說,異常處理的重要性往往會被很多人所忽視。在正規化的軟體開發過程中,異常處理往往扮演了一個重要的角色。我自己學習軟體開發也有兩年了,在此之前沒有意識到異常處理的重要性。於是為此查了一些資料,重新學習了一下異常處理。在此總結一下學習成果。
      一般的,傳統錯誤處理方法大致可以分為返回碼機制和全域變數兩種。
      1。返回碼機制
      這種處理錯誤的方法比較實用和簡單,這也是我以前經常採取的手段之一。對於小型的程式來說這種異常處理機制的缺點暴露不明顯,對於一個需要多人開發的軟體程式來說,它的弊端就非常明顯了!因為對於一個模組的實現者來說有的人傳回值0代表錯誤;有的人傳回值0代表正確,非0代表錯誤。解決方案可以用一致性的條文來控制。通常的,這些返回碼就在一個公用的.h檔案中以宏的形式存在。這樣暫時解決了團隊之間的一致性,但是這些都不是標準,相容性太差。對於如此多的返回碼要分別解釋各自的意義,從調用者的角度來說,需要分別對返回碼進行檢查來處理異常,這樣的代碼往往就顯得非常的臃腫,大大降低了可讀性。
      2。全域變數
      通過用一個全域變數來表示一次操作是否成功。這個方法在多線程中就非常頭痛。另外在每次處理完異常之後就要複位這個變數,如果忘記這個步驟,就會引起其他動作的誤解。
      C++的異常處理機制彌補了傳統錯誤處理方法的弊端,當然它的代價就是效能上的消耗。但是換來了代碼品質的改進,提高了代碼間的維護性,這種消耗完全值得。

      結構化異常處理和C++異常處理的區別:
      結構化異常處理(SEH)是可用於任何程式設計語言的作業系統裝置。而異常處理只能用於編寫C++代碼。如果在編寫C++程式,應該使用C++異常處理而不是SEH。理由是C++異常處理是語言的一部分,編譯器知道C++類對象是什麼。也就是編譯器能夠自動產生代碼來調用C++對象解構函式,保證對象的清除。但是也應該知道VC編譯器已經利用作業系統的SEH實現了C++異常處理。所以當建立一個try塊時,編譯器就產生一個__try塊。一個catch變成了SEH異常過濾器,並且catch中的代碼變成了__except塊中的代碼。每寫一條throw語句時,編譯器就產生一個對windows的RaiseException函數的調用。用於throw語句的變數傳遞給RaiseException作為附加的參數。對於SEH的詳細說明在《Windows核心編程》的第23章有詳細介紹。
      在使用C++異常處理的時候要注意幾點:
      1.異常的類型要一致。(見function1)
      2.對於傳遞大型類對象時盡量使用引用的方式。(見function1)
      3.盡量保持try塊中拋出的異常在被處理的狀態(提供足夠的catch子句)(見function2)
class PrintErr
{
public:
 PrintErr(int i) {m_iNum = i;}
 int m_iNum;
};
class TypeErr{};

void Myprint(char* p) throw(PrintErr)
{
 if(p == NULL)
  throw PrintErr(10);
 //...
}

void function1()
{
 try
 {
  Myprint(NULL);//  拋出一個PrintErr的異常
 }
// catch(int i) { /*..*/ }   異常的類型要一致
 catch(PrintErr& err)//  使用引用的方式傳遞異常,防止不必要的拷貝大型類對象
 {
  //...
  throw;//  如果異常在這裡無法完成,可以rethrow這個異常(throw err)
 }
 catch(...)// 對於其他類型的異常進行處理
 {
 }
}

void function2()
{
 try
 {
  Myprint(NULL);
 }
// 沒有為PrintErr提供catch子句,系統自動調用庫函數terminate()。
 catch (TypeErr& err)
 {
  //...
 }
}

void function3() throw()//  這個函數被定義成不拋出任何異常
{
 Myprint(NULL);//  error
}

int main(int argc, char* argv[])
{
 try
 {
  function1();
 }
 catch (PrintErr& err)
 {
  //...對rethrow的異常進行處理
 }
 return 0;
}

      通常使用Visual C++編譯異常處理時會出現warning C4290: C++ Exception Specification ignored。這是因為Visual C++在編譯期檢查異常規範申明,但在運行期忽略它們。你可以給函數加上異常申明,編譯器會正確地分析它們,但在運行期這個申明沒有效果,就象根本沒有寫過。所以可以使用#pragma warning(disable:4290)屏蔽這條警告。

      對於初學軟體開發的人來說,異常處理的重要性往往會被很多人所忽視。在正規化的軟體開發過程中,異常處理往往扮演了一個重要的角色。我自己學習軟體開發也有兩年了,在此之前沒有意識到異常處理的重要性。於是為此查了一些資料,重新學習了一下異常處理。在此總結一下學習成果。
      一般的,傳統錯誤處理方法大致可以分為返回碼機制和全域變數兩種。
      1。返回碼機制
      這種處理錯誤的方法比較實用和簡單,這也是我以前經常採取的手段之一。對於小型的程式來說這種異常處理機制的缺點暴露不明顯,對於一個需要多人開發的軟體程式來說,它的弊端就非常明顯了!因為對於一個模組的實現者來說有的人傳回值0代表錯誤;有的人傳回值0代表正確,非0代表錯誤。解決方案可以用一致性的條文來控制。通常的,這些返回碼就在一個公用的.h檔案中以宏的形式存在。這樣暫時解決了團隊之間的一致性,但是這些都不是標準,相容性太差。對於如此多的返回碼要分別解釋各自的意義,從調用者的角度來說,需要分別對返回碼進行檢查來處理異常,這樣的代碼往往就顯得非常的臃腫,大大降低了可讀性。
      2。全域變數
      通過用一個全域變數來表示一次操作是否成功。這個方法在多線程中就非常頭痛。另外在每次處理完異常之後就要複位這個變數,如果忘記這個步驟,就會引起其他動作的誤解。
      C++的異常處理機制彌補了傳統錯誤處理方法的弊端,當然它的代價就是效能上的消耗。但是換來了代碼品質的改進,提高了代碼間的維護性,這種消耗完全值得。

      結構化異常處理和C++異常處理的區別:
      結構化異常處理(SEH)是可用於任何程式設計語言的作業系統裝置。而異常處理只能用於編寫C++代碼。如果在編寫C++程式,應該使用C++異常處理而不是SEH。理由是C++異常處理是語言的一部分,編譯器知道C++類對象是什麼。也就是編譯器能夠自動產生代碼來調用C++對象解構函式,保證對象的清除。但是也應該知道VC編譯器已經利用作業系統的SEH實現了C++異常處理。所以當建立一個try塊時,編譯器就產生一個__try塊。一個catch變成了SEH異常過濾器,並且catch中的代碼變成了__except塊中的代碼。每寫一條throw語句時,編譯器就產生一個對windows的RaiseException函數的調用。用於throw語句的變數傳遞給RaiseException作為附加的參數。對於SEH的詳細說明在《Windows核心編程》的第23章有詳細介紹。
      在使用C++異常處理的時候要注意幾點:
      1.異常的類型要一致。(見function1)
      2.對於傳遞大型類對象時盡量使用引用的方式。(見function1)
      3.盡量保持try塊中拋出的異常在被處理的狀態(提供足夠的catch子句)(見function2)
class PrintErr
{
public:
 PrintErr(int i) {m_iNum = i;}
 int m_iNum;
};
class TypeErr{};

void Myprint(char* p) throw(PrintErr)
{
 if(p == NULL)
  throw PrintErr(10);
 //...
}

void function1()
{
 try
 {
  Myprint(NULL);//  拋出一個PrintErr的異常
 }
// catch(int i) { /*..*/ }   異常的類型要一致
 catch(PrintErr& err)//  使用引用的方式傳遞異常,防止不必要的拷貝大型類對象
 {
  //...
  throw;//  如果異常在這裡無法完成,可以rethrow這個異常(throw err)
 }
 catch(...)// 對於其他類型的異常進行處理
 {
 }
}

void function2()
{
 try
 {
  Myprint(NULL);
 }
// 沒有為PrintErr提供catch子句,系統自動調用庫函數terminate()。
 catch (TypeErr& err)
 {
  //...
 }
}

void function3() throw()//  這個函數被定義成不拋出任何異常
{
 Myprint(NULL);//  error
}

int main(int argc, char* argv[])
{
 try
 {
  function1();
 }
 catch (PrintErr& err)
 {
  //...對rethrow的異常進行處理
 }
 return 0;
}

      通常使用Visual C++編譯異常處理時會出現warning C4290: C++ Exception Specification ignored。這是因為Visual C++在編譯期檢查異常規範申明,但在運行期忽略它們。你可以給函數加上異常申明,編譯器會正確地分析它們,但在運行期這個申明沒有效果,就象根本沒有寫過。所以可以使用#pragma warning(disable:4290)屏蔽這條警告。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.