windows異常處理 __try __except

來源:互聯網
上載者:User

 

 

try-except用法

 

  try except是windows 系統專屬的異常處理模型,windows的異常處理模式,稱為SEH( structured exception handling ),

       SEH的異常處理模型主要由try-except語句來完成,與標準的try catch相似。與C++異常處理模型使用catch關鍵字來定義異常處理模組,而SEH是採用__except關鍵

 

字來定義。並且,catch關鍵字後面往往好像接受一個函數參數一樣,可以是各種類型的異常資料對象;但是__except關鍵字則不同,它後面跟的卻是一個運算式.

 

我們知道,函數調用也是一個運算式。

 

    我們來看下面這個例子,這個例子是用來處理棧溢出的異常。    

long WINAPI FilterFunc(DWORD dwExceptionCode)

{

return (dwExceptionCode == STATUS_STACK_OVERFLOW) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;

}

 

UINT WINAPI ThreadFunc(LPVOID param)

{

__try

{

                   // guarded code 

}

__except (FilterFunc(GetExceptionCode()))

{

// 如果是棧溢出,進行處理。

}

    return  TRUEt;    

}

 

except參數的值有以下三種:

       EXCEPTION_CONTINUE_EXECUTION (–1)     異常被忽略,控制流程將在異常出現的點之後,繼續恢複運行。

  EXCEPTION_CONTINUE_SEARCH (0)          異常不被識別,也即當前的這個__except模組不是這個異常錯誤所對應的正確的異常處理模組。系統將繼續到上一try-

 

except域中繼續尋找一個恰當的__except模組。

  EXCEPTION_EXECUTE_HANDLER (1)         異常已經被識別,控制流程將進入到__except模組中運行異常處理代碼

 

try-except的關鍵是如何在__except模組中獲得異常錯誤的相關資訊.

Windows提供了兩個API函數來擷取異常資訊:

LPEXCEPTION_POINTERS GetExceptionInformation(VOID); //取得異常相關資訊

DWORD GetExceptionCode(VOID); // 取得異常編號

 

GetExceptionCode()返回異常編號,而GetExceptionInformation()返回更豐富的資訊,EXCEPTION_POINTERS結構如下,

typedef struct _EXCEPTION_POINTERS { // exp 

PEXCEPTION_RECORD ExceptionRecord; 

PCONTEXT ContextRecord; 

} EXCEPTION_POINTERS;

 

 

其中EXCEPTION_RECORD類型,它記錄了一些與異常相關的資訊;而CONTEXT資料結構體中記錄了異常發生時,線程當時的上下文環境,主要包括寄存器的值。

 

有了這些資訊,__except模組便可以對異常錯誤進行很好的分類和恢複處理,通常我們需要一個過濾函數來輔助。一般稱為是filterfunction.過濾函數只過濾需要處

 

理的異常。

 

int exception_access_violation_filter(LPEXCEPTION_POINTERS p_exinfo)

{

    if(p_exinfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)

    {

        messagebox("access vialation exceptionn");

       return EXCEPTION_EXECUTE_HANDLER ; //告訴except處理這個異常

    }

    else return EXCEPTION_CONTINUE_SEARCH; //不告訴except處理這個異常

}

 

int exception_int_divide_by_zero_filter(LPEXCEPTION_POINTERS p_exinfo)

{

    if(p_exinfo->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)

    {

 

        return  EXCEPTION_EXECUTE_HANDLER; //告訴except處理這個異常

    }

   else return EXCEPTION_CONTINUE_SEARCH; //不告訴except處理這個異常

}

 

 

於是,你可以這樣寫這段異常處理代碼:

__try

{

  // guarded code

}

__except(exception_access_violation_filter(GetExceptionInformation()))

{

//

}

 

__try

{

  // guarded code

}

__exceptexception_int_divide_by_zero_filter(GetExceptionInformation()))

{

//exception handling

}

 

SEH異常處理模型中,也可以拋出一個異常。對應的WindowsAPI函數是RaiseException,

VOID RaiseException(

DWORD dwExceptionCode, // 異常的編號

DWORD dwExceptionFlags, // 異常標記

DWORD nNumberOfArguments, // 參數個數

CONST DWORD *lpArguments //  參數數組首地址

);

通常,後三個參數基本不用

SEH異常處理還有try-finally.類似於java裡的try-catch-finally.但是SEH的try只能和except和finally兩者之間的一個搭配,不能有try-except-finnaly. 

 

 C++異常模型用try-catch文法定義,而SEH異常模型則用try-except文法,與C++異常模型相似,try-except也支援多層的try-except嵌套。

 try-except模型中,一個try塊只能是有一個except塊;而C++異常模型中,一個try塊可以有多個catch塊。

 C++異常模型是按照異常對象的類型來進行匹配尋找的;而try-except模型則不同,它通過一個運算式的值來進行判斷.

  __except關鍵字後面跟的運算式,它可以是各種類型的運算式,例如,它可以是一個函數調用,或是一個條件運算式,或是一個逗號運算式,或乾脆就是一個整

 

型常量等等。最常用的是一個函數運算式,並且通過利用GetExceptionCode()或GetExceptionInformation ()函數來擷取當前的異常錯誤資訊,便於程式員有效控制異常

 

錯誤的分類處理。

SEH異常處理模型中,異常通過RaiseException()函數拋出。RaiseException()函數的作用類似於C++異常模型中的throw。

關於SEH異常處理更詳細的資料,你可以去看windows via c/c++這本書,中文譯名是windows核心編程。不過還是建議你看英文原版,翻譯的版本品質不高。

 

相關文章

聯繫我們

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