SEH:__try__leave__finally__exception

__try

{

 // condition test

__leave;

 //another conditon test

 __leave;

//so on

}

__finally

{

//do some clean up job here

}

 

 

#include "stdafx.h"
#include <windows.h>
#include <excpt.h>

int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)

if (code == EXCEPTION_ACCESS_VIOLATION)
{  
return EXCEPTION_EXECUTE_HANDLER;//捕獲到異常  

else
{  
return EXCEPTION_CONTINUE_SEARCH;  

}


int main(int argc, char* argv[])
{
int* p = NULL;   // pointer to NULL

 int szBuf[] = {1};
p = szBuf;

 __try
{  
__try
{   
puts("try"); 
printf("%d/n", *p);//puts(p);

  // __leave;
// printf("aaa");
//*p = 13;    // causes an access violation exception;

}
__finally
{   
puts(AbnormalTermination() ? "abnormal" : "normal");   
}

}
__except(filter(GetExceptionCode(), GetExceptionInformation()))
{  
puts("except");

return 0;
}

 

 

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核心編程。不過還是建議你看英文原版,翻譯的版本質量不高。

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