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