windows異常處理__try__except

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核心編程。不過還是建議你看英文原版,翻譯的版本質量不高。
————————————————
版權聲明:本文爲CSDN博主「xiahouchunhong」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/xiahouchunhong/article/details/83967327

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