此異常非彼異常(續)

來源:互聯網
上載者:User

轉載請註明出處

作者:小馬

上一篇文章說過,要寫一個關於SEH的博文,實現seh與c++ try/catch的整合或混合使用.
因為通過vc或vs設定的方法來處理有種種的缺點(可參見上篇文章).

 

以下所有代碼均在vs2005 下測試.

 

明確一點, seh是windows特有的, 所以它不具移植性.

windows SEH捕捉代碼塊為 __try/ __except 塊, 下面這段代碼展示如何使用它:

__try{  int *p = NULL;  *p = 10;}__except(EXCEPTION_EXECUTE_HANDLER){  cout << "seh exception happened" << endl;}

在__try塊裡,給一個非法的記憶體位址賦值, 這是一個典型的seh異常,所以程式的結果會輸出:
seh exception happened

 

__except的參數比較有意思, 因為它可以是一個運算式, 這樣處理帶來的是靈活性. 當__try塊裡有異常出現時, 它會執行__except裡的運算式(當有異常出現時, __except塊的語句可能不會被執行, 但運算式一定會被執行), 這個運算式執行的結果決定了異常如何被處理.運算式執行的結果一般有三個,msdn裡如是說:

EXCEPTION_CONTINUE_EXECUTION (–1)   Exception is dismissed. Continue execution at the point where the exception occurred.  EXCEPTION_CONTINUE_SEARCH (0)   Exception is not recognized. Continue to search up the stack for a handler, first for containing try-except statements, then for handlers with the next highest precedence.  EXCEPTION_EXECUTE_HANDLER (1)   Exception is recognized. Transfer control to the exception handler by executing the __except compound statement, then continue execution after the __except block. 

 

 

意思很明顯, 只有__except的運算式的結果是EXCEPTION_EXECUTE_HANDLER時, 才會執行__except裡的語句(其它兩個不解釋了).
EXCEPTION_EXECUTE_HANDLER表示異常可以被識別, 所以交給__except去處理. 像上面的程式碼片段, 直接讓__except的參數為EXCEPTION_EXECUTE_HANDLER, 所以"seh exception happened"會列印出來.

 

實際項目的應用稍微複雜一些, 往往不是這樣直接給__except的參數賦值, 想一下, 如果一段代碼出現了異常, 我們肯定希望知道哪種異常發生了, 也就是要識別這種異常, 我們需要寫一個過濾函數(因為__except的參數是運算式, 所以可以是函數調用), 過濾出我們可識別的異常,讓這些異常成為EXCEPTION_EXECUTE_HANDLER, 這樣才能在__except裡去處理. 代碼如下:

 

int FilterFunc(DWORD exCode){ if (exCode == EXCEPTION_ACCESS_VIOLATION)//非法訪問 {  cout << "EXCEPTION_ACCESS_VIOLATION" << endl;  return EXCEPTION_EXECUTE_HANDLER; } else if (exCode == EXCEPTION_STACK_OVERFLOW)//堆疊溢位 {  cout << "EXCEPTION_STACK_OVERFLOW" << endl;  return EXCEPTION_EXECUTE_HANDLER; } else if (exCode == EXCEPTION_INT_DIVIDE_BY_ZERO)//除數為0 {  cout << "EXCEPTION_INT_DIVIDE_BY_ZERO" << endl;  return EXCEPTION_EXECUTE_HANDLER; } else {  cout << "unknown exception" << endl;  return EXCEPTION_CONTINUE_SEARCH; }}

然後可以這樣用:

__try {   int *p = NULL;   *p = 10; } __except(FilterFunc(GetExceptionCode())) {   cout << "seh exception happened" << endl; }

輸出:
EXCEPTION_ACCESS_VIOLATION
seh exception happened

 

對於GetExceptionCode函數,只需要知道它是win32定義的一個宏,可以返回異常代碼就行了.

 

我們還可以把FilterFunc完善一些, 更詳細的跟蹤異常, 代碼如下:

int FilterFunc(DWORD exCode, char *fileName, int nLine, char *time){ if (exCode == EXCEPTION_ACCESS_VIOLATION)//非法訪問 {  cout << "EXCEPTION_ACCESS_VIOLATION" << endl;  cout << "at " << fileName << ",line: " << nLine << ",time: " << time <<endl;  return EXCEPTION_EXECUTE_HANDLER; } else if (exCode == EXCEPTION_STACK_OVERFLOW)//堆疊溢位 {  cout << "EXCEPTION_STACK_OVERFLOW" << endl;  cout << "at " << fileName << ",line: " << nLine << ",time: " << time <<endl;  return EXCEPTION_EXECUTE_HANDLER; } else if (exCode == EXCEPTION_INT_DIVIDE_BY_ZERO)//除數為0 {  cout << "EXCEPTION_INT_DIVIDE_BY_ZERO" << endl;  cout << "at " << fileName << ",line: " << nLine << ",time: " << time <<endl;  return EXCEPTION_EXECUTE_HANDLER; } else {  cout << "unknown exception" << endl;  cout << "at " << fileName << ",line: " << nLine << ",time: " << time <<endl;  return EXCEPTION_CONTINUE_SEARCH; }}

 

然後這樣調用:

__try{  int *p = NULL;  *p = 10;}__except(FilterFunc(GetExceptionCode(), __FILE__, __LINE__, __TIME__)){   cout << "seh exception happened" << endl;}

結果輸出:
EXCEPTION_ACCESS_VIOLATION
at d:\study\test\exceptiontest\exceptiontest\exceptiontest.cpp,line: 36,time: 14
:34:50
seh exception happened

好了,以後我們的代碼中,就可以用try/catch捕獲throw的異常, 用__try/__except捕獲seh異常. 各司其職.

最後有一句話要說, 微軟希望我們在c裡才有__try/__except, c++還是用try/catch,不要用前者. 原因是多方面的,不多說了.

 

思考一個問題, 如果不用__try/__except,如何在c++的代碼中SEH呢?

等下篇文章吧......

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.