青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

大龍的博客

常用鏈接

統(tǒng)計(jì)

最新評(píng)論

SEH的強(qiáng)大功能之一(轉(zhuǎn))

從本篇文章開始,將全面闡述__try,__except,__finally,__leave異常模型機(jī)制,它也即是Windows系列操作系統(tǒng)平臺(tái)上提供的SEH模型。主人公阿愚將在這里與大家分享SEH的學(xué)習(xí)過程和經(jīng)驗(yàn)總結(jié)。

  SEH有兩項(xiàng)非常強(qiáng)大的功能。當(dāng)然,首先是異常處理模型了,因此,這篇文章首先深入闡述SEH提供的異常處理模型。另外,SEH還有一個(gè)特別強(qiáng)大的功能,這將在下一篇文章中進(jìn)行詳細(xì)介紹。

try-except入門

  SEH的異常處理模型主要由try-except語句來完成,它與標(biāo)準(zhǔn)C++所定義的異常處理模型非常類似,也都是可以定義出受監(jiān)控的代碼模塊,以及定義異常處理模塊等。還是老辦法,看一個(gè)例子先,代碼如下:

//seh-test.c
#include <stdio.h>

void main()
{
puts("hello");
// 定義受監(jiān)控的代碼模塊
__try
{
puts("in try");
}
//定義異常處理模塊
__except(1)
{
puts("in except");
}
puts("world");
}

  呵呵!是不是很簡(jiǎn)單,而且與C++異常處理模型很相似。當(dāng)然,為了與C++異常處理模型相區(qū)別,VC編譯器對(duì)關(guān)鍵字做了少許變動(dòng)。首先是在每個(gè)關(guān)鍵字加上兩個(gè)下劃線作為前綴,這樣既保持了語義上的一致性,另外也盡最大可能來避免了關(guān)鍵字的有可能造成名字沖突而引起的麻煩等;其次,C++異常處理模型是使用catch關(guān)鍵字來定義異常處理模塊,而SEH是采用__except關(guān)鍵字來定義。并且,catch關(guān)鍵字后面往往好像接受一個(gè)函數(shù)參數(shù)一樣,可以是各種類型的異常數(shù)據(jù)對(duì)象;但是__except關(guān)鍵字則不同,它后面跟的卻是一個(gè)表達(dá)式(可以是各種類型的表達(dá)式,后面會(huì)進(jìn)一步分析)。

try-except進(jìn)階

  與C++異常處理模型很相似,在一個(gè)函數(shù)中,可以有多個(gè)try-except語句。它們可以是一個(gè)平面的線性結(jié)構(gòu),也可以是分層的嵌套結(jié)構(gòu)。例程代碼如下:

// 例程1
// 平面的線性結(jié)構(gòu)
#include <stdio.h>

void main()
{
puts("hello");
__try
{
puts("in try");
}
__except(1)
{
puts("in except");
}

// 又一個(gè)try-except語句
__try
{
puts("in try");
}
__except(1)
{
puts("in except");
}

puts("world");
}


// 例程2
// 分層的嵌套結(jié)構(gòu)
#include <stdio.h>

void main()
{
puts("hello");
__try
{
puts("in try");
// 又一個(gè)try-except語句
__try
{
puts("in try");
}
__except(1)
{
puts("in except");
}
}
__except(1)
{
puts("in except");
}

puts("world");
}

 

// 例程3
// 分層的嵌套在__except模塊中
#include <stdio.h>

void main()
{
puts("hello");
__try
{
puts("in try");
}
__except(1)
{
// 又一個(gè)try-except語句
__try
{
puts("in try");
}
__except(1)
{
puts("in except");
}

puts("in except");
}

puts("world");
}

try-except異常處理規(guī)則

  try-except異常處理規(guī)則與C++異常處理模型有相似之處,例如,它們都是向上逐級(jí)搜索恰當(dāng)?shù)漠惓L幚砟K,包括跨函數(shù)的多層嵌套try- except語句。但是,它們的處理規(guī)則也有另外一些很大的不同之處,例如查找匹配恰當(dāng)?shù)漠惓L幚砟K的過程,在C++異常處理模型中,它是通過異常對(duì)象的類型來匹配;但是在try-except語句的異常處理規(guī)則中,則是通過__except關(guān)鍵字后面括號(hào)中的表達(dá)式的值來匹配查找正確的異常處理模塊。還是看看MSDN中怎么說的吧!摘略如下:

The compound statement after the __try clause is the body or guarded section. The compound statement after the __except clause is the exception handler. The handler specifies a set of actions to be taken if an exception is raised during execution of the body of the guarded section. Execution proceeds as follows:
1. The guarded section is executed.
2. If no exception occurs during execution of the guarded section, execution continues at the statement after the __except clause.
3. If an exception occurs during execution of the guarded section or in any routine the guarded section calls, the __except expression is evaluated and the value determines how the exception is handled. There are three values:
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 at the assembly instruction that was executing when the exception was raised.
Because the __except expression is evaluated as a C expression, it is limited to a single value, the conditional-expression operator, or the comma operator. If more extensive processing is required, the expression can call a routine that returns one of the three values listed above.

  對(duì)查找匹配恰當(dāng)?shù)漠惓L幚砟K的過程等幾條規(guī)則翻譯如下:
  1. 受監(jiān)控的代碼模塊被執(zhí)行(也即__try定義的模塊代碼);
  2. 如果上面的代碼執(zhí)行過程中,沒有出現(xiàn)異常的話,那么控制流將轉(zhuǎn)入到__except子句之后的代碼模塊中;
  3. 否則,如果出現(xiàn)異常的話,那么控制流將進(jìn)入到__except后面的表達(dá)式中,也即首先計(jì)算這個(gè)表達(dá)式的值,之后再根據(jù)這個(gè)值,來決定做出相應(yīng)的處理。這個(gè)值有三種情況,如下:
  EXCEPTION_CONTINUE_EXECUTION (–1) 異常被忽略,控制流將在異常出現(xiàn)的點(diǎn)之后,繼續(xù)恢復(fù)運(yùn)行。
  EXCEPTION_CONTINUE_SEARCH (0) 異常不被識(shí)別,也即當(dāng)前的這個(gè)__except模塊不是這個(gè)異常錯(cuò)誤所對(duì)應(yīng)的正確的異常處理模塊。系統(tǒng)將繼續(xù)到上一層的try-except域中繼續(xù)查找一個(gè)恰當(dāng)?shù)腳_except模塊。
  EXCEPTION_EXECUTE_HANDLER (1) 異常已經(jīng)被識(shí)別,也即當(dāng)前的這個(gè)異常錯(cuò)誤,系統(tǒng)已經(jīng)找到了并能夠確認(rèn),這個(gè)__except模塊就是正確的異常處理模塊。控制流將進(jìn)入到__except模塊中。

  上面的規(guī)則其實(shí)挺簡(jiǎn)單的,很好理解。當(dāng)然,這個(gè)規(guī)則也非常的嚴(yán)謹(jǐn),它能很好的滿足開發(fā)人員的各種需求,滿足程序員對(duì)異常處理的分類處理的要求,它能夠給程序員提供一個(gè)靈活的控制手段。

  其中比較特殊的就是__except關(guān)鍵字后面跟的表達(dá)式,它可以是各種類型的表達(dá)式,例如,它可以是一個(gè)函數(shù)調(diào)用,或是一個(gè)條件表達(dá)式,或是一個(gè)逗號(hào)表達(dá)式,或干脆就是一個(gè)整型常量等等。例如代碼如下:

// seh-test.c
// 異常處理模塊的查找過程演示
#include <stdio.h>

int seh_filer()
{
return 0;
}

void test()
{
__try
{
int* p;

puts("test()函數(shù)的try塊中");

// 下面將導(dǎo)致一個(gè)異常
p = 0;
*p = 45;
}
// 注意,__except關(guān)鍵字后面的表達(dá)式是一個(gè)函數(shù)表達(dá)式
// 而且這個(gè)函數(shù)將返回0,所以控制流進(jìn)入到上一層
// 的try-except語句中繼續(xù)查找
__except(seh_filer())
{
puts("test()函數(shù)的except塊中");
}
}

void main()
{
puts("hello");
__try
{
puts("main()函數(shù)的try塊中");

// 注意,這個(gè)函數(shù)的調(diào)用過程中,有可能出現(xiàn)一些異常
test();
}
// 注意,這個(gè)表達(dá)式是一個(gè)逗號(hào)表達(dá)式
// 它前部分打印出一條message,后部分是
// 一個(gè)常量,所以這個(gè)值也即為整個(gè)表達(dá)式
// 的值,因此系統(tǒng)找到了__except定義的異
// 常處理模塊,控制流進(jìn)入到__except模塊里面
__except(puts("in filter"), 1)
{
puts("main()函數(shù)的except塊中");
}

puts("world");
}

  上面的程序運(yùn)行結(jié)果如下:
  hello
  main()函數(shù)的try塊中
  test()函數(shù)的try塊中
  in filter
  main()函數(shù)的except塊中
  world
  Press any key to continue

  這種運(yùn)行結(jié)果應(yīng)該是在意料之中吧!為了對(duì)它的流程進(jìn)行更清楚的分析,下圖描述出了程序的運(yùn)行控制流轉(zhuǎn)移過程,如下。

http://byfiles.storage.msn.com/x1pN1mp8dKYgTFQGzKRebME6105or51BGbjDrskKQ5x3cw-RNCRExH00cuzP8U6qAybuiCE9msw4yGhML-hVWfFOK8DnWPKA9WtlamUEAPnYIJs4c-bXtKEVQ

  另外,對(duì)于__except關(guān)鍵字后面表達(dá)式的值,上面的規(guī)則中已經(jīng)做了詳細(xì)規(guī)定。它們有三種值,其中如果為0,那么系統(tǒng)繼續(xù)查找;如果為1,表示系統(tǒng)已經(jīng)找到正確的異常處理模塊。其實(shí)這兩個(gè)值都很好理解,可是如果值為-1的話,那么處理將比較特殊,上面也提到了,此種情況下,“異常被忽略,控制流將在異常出現(xiàn)的點(diǎn)之后,繼續(xù)恢復(fù)運(yùn)行。”實(shí)際上,這就等同于說,程序的執(zhí)行過程將不受干擾,好像異常從來沒有發(fā)生一樣。看一個(gè)例程吧!代碼如下:

#include <stdio.h>

void main()
{
int j, zero;

puts("hello");
__try
{
puts("main()函數(shù)的try塊中");

zero = 0;
j = 10;
// 下面將導(dǎo)致一個(gè)異常
j = 45 / zero;

// 注意,異常出現(xiàn)后,程序控制流又恢復(fù)到了這里
printf("這里會(huì)執(zhí)行到嗎?值有如何呢?j=%d \n", j);
}
// 注意,這里把zero變量賦值為1,試圖恢復(fù)錯(cuò)誤,
// 當(dāng)控制流恢復(fù)到原來異常點(diǎn)時(shí),避免了異常的再次發(fā)生
__except(puts("in filter"), zero = 1, -1)
{
puts("main()函數(shù)的except塊中");
}

puts("world");
}

上面的程序運(yùn)行結(jié)果如下:
hello
main()函數(shù)的try塊中
in filter
這里會(huì)執(zhí)行到嗎?值有如何呢?j=45
world
Press any key to continue

  呵呵!厲害吧!要知道C++異常處理模型可沒有這樣的能力。但是請(qǐng)注意,一般這項(xiàng)功能不能輕易采用,為什么呢?因?yàn)樗鼤?huì)導(dǎo)致不穩(wěn)定,再看下面一個(gè)示例,代碼如下:

#include <stdio.h>

void main()
{
int* p, a;

puts("hello");
__try
{
puts("main()函數(shù)的try塊中");

// 下面將導(dǎo)致一個(gè)異常
p = 0;
*p = 45;

printf("這里會(huì)執(zhí)行到嗎?值有如何呢?p=%d \n", *p);
}
// 注意,這里把p指針賦了一個(gè)合法的值,也即說,
// 當(dāng)控制流恢復(fù)到原來異常點(diǎn)時(shí),異常將不會(huì)再次發(fā)生
__except(puts("in filter"), p = &a, -1)
{
puts("main()函數(shù)的except塊中");
}

puts("world");
}

  呵呵!大家猜猜上面的程序的運(yùn)行結(jié)果如何呢?是不是和剛才的那個(gè)例子一樣,異常也得以被恢復(fù)了。朋友們!還是親自運(yùn)行測(cè)試一把。哈哈!程序運(yùn)行結(jié)果是死了,進(jìn)行一個(gè)無限循環(huán)當(dāng)中,并且控制終端內(nèi)不斷輸出“in filter”信息。為什么會(huì)出現(xiàn)這種情況,難道MSDN中有關(guān)的闡述的有問題嗎?或這個(gè)異常處理模型實(shí)現(xiàn)上存在BUG?NO!不是這樣的,實(shí)際上這就是由于表達(dá)式返回-1值時(shí),給程序所帶來的不穩(wěn)定性。當(dāng)然,MSDN中有關(guān)的闡述也沒有錯(cuò),那么究竟具體原因是為何呢?這是因?yàn)椋磉_(dá)式返回-1值時(shí),系統(tǒng)將把控制流恢復(fù)到異常出現(xiàn)點(diǎn)之后繼續(xù)運(yùn)行。這意味著什么呢?也許大家都明白了,它這里的異常恢復(fù)點(diǎn)是基于一條機(jī)器指令級(jí)別上的。這樣就有很大的風(fēng)險(xiǎn),因?yàn)樯厦娴睦讨校^的異常恢復(fù)處理,也即p = &a語句,它實(shí)際上的確改變了p指針值,但是這個(gè)指針值是棧上的某個(gè)內(nèi)存區(qū)域,而真正出現(xiàn)異常時(shí),代表p指針值的很有可能是某個(gè)寄存器。呵呵!是不是挺費(fèi)解的,沒關(guān)系!還是看看調(diào)試界圖吧!如下:

http://byfiles.storage.msn.com/x1pN1mp8dKYgTFQGzKRebME62KovOI2zIOz3rCTVXO99-ku0JJm6Gg--r6FEmfo7NKpWBwPGnL6pvfxPZ2zpd1rP8MhDhEmzvQiib6XZ1TEJqu_HREcahE28g


try-except深入

  上面的內(nèi)容中已經(jīng)對(duì)try-except進(jìn)行了全面的了解,但是有一點(diǎn)還沒有闡述到。那就是如何在__except模塊中獲得異常錯(cuò)誤的相關(guān)信息,這非常關(guān)鍵,它實(shí)際上是進(jìn)行異常錯(cuò)誤處理的前提,也是對(duì)異常進(jìn)行分層分級(jí)別處理的前提。可想而知,如果沒有這些起碼的信息,異常處理如何進(jìn)行?因此獲取異常信息非常的關(guān)鍵。Windows提供了兩個(gè)API函數(shù),如下:

LPEXCEPTION_POINTERS GetExceptionInformation(VOID);
DWORD GetExceptionCode(VOID);

  其中GetExceptionCode()返回錯(cuò)誤代碼,而GetExceptionInformation()返回更全面的信息,看它函數(shù)的聲明,返回了一個(gè)LPEXCEPTION_POINTERS類型的指針變量。那么EXCEPTION_POINTERS結(jié)構(gòu)如何呢?如下,

typedef struct _EXCEPTION_POINTERS { // exp
PEXCEPTION_RECORD ExceptionRecord;
PCONTEXT ContextRecord;
} EXCEPTION_POINTERS;

  呵呵!仔細(xì)瞅瞅,這是不是和上一篇文章中,用戶程序所注冊(cè)的異常處理的回調(diào)函數(shù)的兩個(gè)參數(shù)類型一樣。是的,的確沒錯(cuò)!其中 EXCEPTION_RECORD類型,它記錄了一些與異常相關(guān)的信息;而CONTEXT數(shù)據(jù)結(jié)構(gòu)體中記錄了異常發(fā)生時(shí),線程當(dāng)時(shí)的上下文環(huán)境,主要包括寄存器的值。因此有了這些信息,__except模塊便可以對(duì)異常錯(cuò)誤進(jìn)行很好的分類和恢復(fù)處理。不過特別需要注意的是,這兩個(gè)函數(shù)只能是在 __except后面的括號(hào)中的表達(dá)式作用域內(nèi)有效,否則結(jié)果可能沒有保證(至于為什么,在后面深入分析異常模型的實(shí)現(xiàn)時(shí)候,再做詳細(xì)闡述)。看一個(gè)例程吧!代碼如下:

#include <windows.h>
#include <stdio.h>

int exception_access_violation_filter(LPEXCEPTION_POINTERS p_exinfo)
{
if(p_exinfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
printf("存儲(chǔ)保護(hù)異常\n");
return 1;
}
else return 0;
}

int exception_int_divide_by_zero_filter(LPEXCEPTION_POINTERS p_exinfo)
{
if(p_exinfo->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
{
printf("被0除異常\n");
return 1;
}
else return 0;
}

void main()
{
puts("hello");
__try
{
__try
{
int* p;

// 下面將導(dǎo)致一個(gè)異常
p = 0;
*p = 45;
}
// 注意,__except模塊捕獲一個(gè)存儲(chǔ)保護(hù)異常
__except(exception_access_violation_filter(GetExceptionInformation()))
{
puts("內(nèi)層的except塊中");
}
}
// 注意,__except模塊捕獲一個(gè)被0除異常
__except(exception_int_divide_by_zero_filter(GetExceptionInformation()))
{
puts("外層的except塊中");
}

puts("world");
}

上面的程序運(yùn)行結(jié)果如下:
hello
存儲(chǔ)保護(hù)異常
內(nèi)層的except塊中
world
Press any key to continue

  呵呵!感覺不錯(cuò),大家可以在上面的程序基礎(chǔ)之上改動(dòng)一下,讓它拋出一個(gè)被0除異常,看程序的運(yùn)行結(jié)果是不是如預(yù)期那樣。

  最后還有一點(diǎn)需要闡述,在C++的異常處理模型中,有一個(gè)throw關(guān)鍵字,也即在受監(jiān)控的代碼中拋出一個(gè)異常,那么在SEH異常處理模型中,是不是也應(yīng)該有這樣一個(gè)類似的關(guān)鍵字或函數(shù)呢?是的,沒錯(cuò)!SEH異常處理模型中,對(duì)異常劃分為兩大類,第一種就是上面一些例程中所見到的,這類異常是系統(tǒng)異常,也被稱為硬件異常;還有一類,就是程序中自己拋出異常,被稱為軟件異常。怎么拋出呢?還是Windows提供了的API函數(shù),它的聲明如下:

VOID RaiseException(
DWORD dwExceptionCode, // exception code
DWORD dwExceptionFlags, // continuable exception flag
DWORD nNumberOfArguments, // number of arguments in array
CONST DWORD *lpArguments // address of array of arguments
);

  很簡(jiǎn)單吧!實(shí)際上,在C++的異常處理模型中的throw關(guān)鍵字,最終也是對(duì)RaiseException()函數(shù)的調(diào)用,也即是說,throw是 RaiseException的上層封裝的更高級(jí)一類的函數(shù),這以后再詳細(xì)分析它的代碼實(shí)現(xiàn)。這里還是看一個(gè)簡(jiǎn)單例子吧!代碼如下:

#include <windows.h>
#include <stdio.h>

int seh_filer(int code)
{
switch(code)
{
case EXCEPTION_ACCESS_VIOLATION :
printf("存儲(chǔ)保護(hù)異常,錯(cuò)誤代碼:%x\n", code);
break;
case EXCEPTION_DATATYPE_MISALIGNMENT :
printf("數(shù)據(jù)類型未對(duì)齊異常,錯(cuò)誤代碼:%x\n", code);
break;
case EXCEPTION_BREAKPOINT :
printf("中斷異常,錯(cuò)誤代碼:%x\n", code);
break;
case EXCEPTION_SINGLE_STEP :
printf("單步中斷異常,錯(cuò)誤代碼:%x\n", code);
break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED :
printf("數(shù)組越界異常,錯(cuò)誤代碼:%x\n", code);
break;
case EXCEPTION_FLT_DENORMAL_OPERAND :
case EXCEPTION_FLT_DIVIDE_BY_ZERO :
case EXCEPTION_FLT_INEXACT_RESULT :
case EXCEPTION_FLT_INVALID_OPERATION :
case EXCEPTION_FLT_OVERFLOW :
case EXCEPTION_FLT_STACK_CHECK :
case EXCEPTION_FLT_UNDERFLOW :
printf("浮點(diǎn)數(shù)計(jì)算異常,錯(cuò)誤代碼:%x\n", code);
break;
case EXCEPTION_INT_DIVIDE_BY_ZERO :
printf("被0除異常,錯(cuò)誤代碼:%x\n", code);
break;
case EXCEPTION_INT_OVERFLOW :
printf("數(shù)據(jù)溢出異常,錯(cuò)誤代碼:%x\n", code);
break;
case EXCEPTION_IN_PAGE_ERROR :
printf("頁錯(cuò)誤異常,錯(cuò)誤代碼:%x\n", code);
break;
case EXCEPTION_ILLEGAL_INSTRUCTION :
printf("非法指令異常,錯(cuò)誤代碼:%x\n", code);
break;
case EXCEPTION_STACK_OVERFLOW :
printf("堆棧溢出異常,錯(cuò)誤代碼:%x\n", code);
break;
case EXCEPTION_INVALID_HANDLE :
printf("無效句病異常,錯(cuò)誤代碼:%x\n", code);
break;
default :
if(code & (1<<29))
printf("用戶自定義的軟件異常,錯(cuò)誤代碼:%x\n", code);
else
printf("其它異常,錯(cuò)誤代碼:%x\n", code);
break;
}

return 1;
}

void main()
{
puts("hello");
__try
{
puts("try塊中");

// 注意,主動(dòng)拋出一個(gè)軟異常
RaiseException(0xE0000001, 0, 0, 0);
}
__except(seh_filer(GetExceptionCode()))
{
puts("except塊中");
}

puts("world");
}

上面的程序運(yùn)行結(jié)果如下:
hello
try塊中
用戶自定義的軟件異常,錯(cuò)誤代碼:e0000001
except塊中
world
Press any key to continue

  上面的程序很簡(jiǎn)單,這里不做進(jìn)一步的分析。我們需要重點(diǎn)討論的是,在__except模塊中如何識(shí)別不同的異常,以便對(duì)異常進(jìn)行很好的分類處理。毫無疑問,它當(dāng)然是通過GetExceptionCode()或GetExceptionInformation ()函數(shù)來獲取當(dāng)前的異常錯(cuò)誤代碼,實(shí)際也即是DwExceptionCode字段。異常錯(cuò)誤代碼在winError.h文件中定義,它遵循 Windows系統(tǒng)下統(tǒng)一的錯(cuò)誤代碼的規(guī)則。每個(gè)DWORD被劃分幾個(gè)字段,如下表所示:

http://byfiles.storage.msn.com/x1pN1mp8dKYgTFQGzKRebME6105or51BGbjDrskKQ5x3cw-RNCRExH00cuzP8U6qAybuiCE9msw4yGhML-hVWfFOK8DnWPKA9WtlamUEAPnYIJs4c-bXtKEVQ

  例如我們可以在winbase.h文件中找到EXCEPTION_ACCESS_VIOLATION的值為0 xC0000005,將這個(gè)異常代碼值拆開,來分析看看它的各個(gè)bit位字段的涵義。
C 0 0 0 0 0 0 5 (十六進(jìn)制)
1100 0000 0000 0000 0000 0000 0000 0101 (二進(jìn)制)
第3 0位和第3 1位都是1,表示該異常是一個(gè)嚴(yán)重的錯(cuò)誤,線程可能不能夠繼續(xù)往下運(yùn)行,必須要及時(shí)處理恢復(fù)這個(gè)異常。第2 9位是0,表示系統(tǒng)中已經(jīng)定義了異常代碼。第2 8位是0,留待后用。第1 6 位至2 7位是0,表示是FACILITY_NULL設(shè)備類型,它代表存取異常可發(fā)生在系統(tǒng)中任何地方,不是使用特定設(shè)備才發(fā)生的異常。第0位到第1 5位的值為5,表示異常錯(cuò)誤的代碼。

  如果程序員在程序代碼中,計(jì)劃拋出一些自定義類型的異常,必須要規(guī)劃設(shè)計(jì)好自己的異常類型的劃分,按照上面的規(guī)則來填充異常代碼的各個(gè)字段值,如上面示例程序中拋出一個(gè)異常代碼為0xE0000001軟件異常。

總結(jié)

  (1) C++異常模型用try-catch語法定義,而SEH異常模型則用try-except語法;

  (2) 與C++異常模型相似,try-except也支持多層的try-except嵌套。

  (3) 與C++異常模型不同的是,try-except模型中,一個(gè)try塊只能是有一個(gè)except塊;而C++異常模型中,一個(gè)try塊可以有多個(gè)catch塊。

  (4)與C++異常模型相似,try-except模型中,查找搜索異常模塊的規(guī)則也是逐級(jí)向上進(jìn)行的。但是稍有區(qū)別的是,C++異常模型是按照異常對(duì)象的類型來進(jìn)行匹配查找的;而try-except模型則不同,它通過一個(gè)表達(dá)式的值來進(jìn)行判斷。如果表達(dá)式的值為1 (EXCEPTION_EXECUTE_HANDLER),表示找到了異常處理模塊;如果值為0 (EXCEPTION_CONTINUE_SEARCH),表示繼續(xù)向上一層的try-except域中繼續(xù)查找其它可能匹配的異常處理模塊;如果值為- 1(EXCEPTION_CONTINUE_EXECUTION),表示忽略這個(gè)異常,注意這個(gè)值一般很少用,因?yàn)樗苋菀讓?dǎo)致程序難以預(yù)測(cè)的結(jié)果,例如,死循環(huán),甚至導(dǎo)致程序的崩潰等。

   (5) __except關(guān)鍵字后面跟的表達(dá)式,它可以是各種類型的表達(dá)式,例如,它可以是一個(gè)函數(shù)調(diào)用,或是一個(gè)條件表達(dá)式,或是一個(gè)逗號(hào)表達(dá)式,或干脆就是一個(gè)整型常量等等。最常用的是一個(gè)函數(shù)表達(dá)式,并且通過利用GetExceptionCode()或GetExceptionInformation ()函數(shù)來獲取當(dāng)前的異常錯(cuò)誤信息,便于程序員有效控制異常錯(cuò)誤的分類處理。

   (6) SEH異常處理模型中,異常被劃分為兩大類:系統(tǒng)異常和軟件異常。其中軟件異常通過RaiseException()函數(shù)拋出。RaiseException()函數(shù)的作用類似于C++異常模型中的throw語句。

  本篇文章已經(jīng)對(duì)SEH的異常處理進(jìn)行了比較全面而深入的闡述,相信大家現(xiàn)在已經(jīng)對(duì)SEH的異常處理機(jī)制胸有成竹了。但是SEH的精華僅只如此嗎?非也,朋友們!繼續(xù)到下一篇的文章中,主人公阿愚將和大家一起共同探討SEH模型的另一項(xiàng)重要的機(jī)制,那就是“有效保證資源的清除”。這對(duì)于C程序可太重要了,因?yàn)樵贑++程序中,至少還有對(duì)象的析構(gòu)函數(shù)來保證資源的有效清除,避免資源泄漏,但C語言中則沒有一個(gè)有效的機(jī)制,來完成此等艱巨的任務(wù)。呵呵!SEH 雪中送炭,它提供了完美的解決方案,所以千萬不要錯(cuò)過,一起去看看吧!Let’s go!

posted on 2008-01-25 19:30 大龍 閱讀(801) 評(píng)論(0)  編輯 收藏 引用


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品久久久99| 午夜国产精品视频免费体验区| 亚洲欧美日韩一区二区| 亚洲免费一在线| 欧美在线视频a| 久久久久五月天| 欧美成人乱码一区二区三区| 欧美激情视频在线免费观看 欧美视频免费一| 久久亚洲精品一区二区| 欧美激情aⅴ一区二区三区| 亚洲风情亚aⅴ在线发布| 日韩一级黄色大片| 欧美在线播放一区| 欧美成人有码| 国产精品一区免费观看| 亚洲韩国一区二区三区| 午夜精品久久久久影视| 欧美激情在线狂野欧美精品| 久久久久国产成人精品亚洲午夜| 亚洲精品乱码久久久久久日本蜜臀 | 久久精品国产第一区二区三区最新章节| 亚洲欧美一区二区激情| 久久久精品动漫| 欧美日韩亚洲国产精品| 国内在线观看一区二区三区| 9色精品在线| 久久精品视频在线播放| 亚洲精品久久| 久久久精品性| 国产精品一区二区久激情瑜伽| 久久噜噜亚洲综合| 久久爱www久久做| 欧美一区二区三区在线免费观看| 久久久久在线| 欧美日韩在线亚洲一区蜜芽| 米奇777在线欧美播放| 国产一区二区三区无遮挡| 最新成人在线| 欧美中文字幕久久| 亚洲免费av网站| 农夫在线精品视频免费观看| 国产亚洲人成网站在线观看| 一区二区三区黄色| 欧美激情一区二区在线 | 裸体女人亚洲精品一区| 亚洲网站啪啪| 欧美人成在线| 亚洲精品国产精品国自产在线| 久久久久国内| 午夜精品福利一区二区蜜股av| 国产精品高潮视频| 国产精品99久久久久久宅男| 亚洲欧洲久久| 欧美成人69av| 亚洲精品国产精品国自产观看| 欧美刺激午夜性久久久久久久| 午夜综合激情| 国内精品视频在线观看| 久久精品主播| 久久久www免费人成黑人精品| 国产主播在线一区| 久久久久久有精品国产| 欧美在线免费视屏| 国产一区二区三区无遮挡| 久久久天天操| 老鸭窝91久久精品色噜噜导演| 一区精品久久| 欧美大片国产精品| 欧美精品导航| 亚洲一区二区动漫| 亚洲一区二区三区国产| 国产精品网红福利| 久久久久国产精品厨房| 久久久久欧美精品| 亚洲福利视频网| 亚洲美女精品久久| 国产精品日韩二区| 麻豆久久婷婷| 欧美区视频在线观看| 99热这里只有精品8| 亚洲尤物在线视频观看| 在线精品国产成人综合| 国外成人在线视频网站| 亚洲免费av片| 国产精品久久久久一区二区| 久久精品99国产精品日本| 久久久久国产精品厨房| 亚洲国产欧美一区二区三区同亚洲| 亚洲国产精品成人一区二区| 欧美黄色视屏| 亚洲欧美在线免费观看| 久久久精品国产免大香伊| 亚洲日韩欧美视频| 亚洲精品欧美激情| 国产欧美日韩亚洲精品| 欧美r片在线| 欧美色偷偷大香| 久久一区二区三区av| 欧美理论电影在线观看| 午夜精品久久久99热福利| 久久综合精品一区| 亚洲一区欧美二区| 久久亚洲精品一区| 亚洲欧美久久久久一区二区三区| 久久精品一区二区国产| 亚洲一区二区三区乱码aⅴ蜜桃女| 久久久久国产精品麻豆ai换脸| 亚洲综合欧美| 欧美精品高清视频| 久久中文在线| 国产农村妇女精品一区二区| 亚洲国产精品久久久久婷婷884 | 亚洲精选中文字幕| 精品成人一区| 亚洲永久在线观看| 日韩午夜高潮| 久久综合九色| 看欧美日韩国产| 国产亚洲欧美一区二区| 在线视频日韩| 在线中文字幕不卡| 欧美成人精品影院| 免费在线看成人av| 狠狠综合久久av一区二区老牛| 中文在线资源观看网站视频免费不卡 | 久久青草久久| 国产农村妇女毛片精品久久莱园子| 亚洲精品在线一区二区| 亚洲人成在线观看网站高清| 久久久久久**毛片大全| 久久精品综合| 国内精品久久久| 欧美在线精品免播放器视频| 久久国产精品色婷婷| 亚洲国产成人在线播放| 欧美在线观看视频在线| 欧美日韩一区二区三区高清| 亚洲经典一区| 一本色道久久综合亚洲精品高清 | 欧美一区=区| 久久久xxx| 国产综合亚洲精品一区二| 午夜精品福利在线| 久久精品国产77777蜜臀 | 在线亚洲成人| 欧美日韩在线高清| 亚洲午夜激情免费视频| 亚洲欧美视频在线观看| 国产精品高潮呻吟久久| 亚洲一区二三| 欧美在线观看网站| 激情自拍一区| 免费观看亚洲视频大全| 亚洲精品美女久久久久| 一区二区三区国产盗摄| 国产精品户外野外| 欧美一区二区日韩一区二区| 免费观看国产成人| 一本色道精品久久一区二区三区| 欧美日韩在线大尺度| 亚洲欧美久久久久一区二区三区| 久久婷婷国产综合精品青草| 亚洲国产精品成人一区二区| 欧美区日韩区| 亚洲男女自偷自拍图片另类| 女同性一区二区三区人了人一| 99re8这里有精品热视频免费 | 欧美一级午夜免费电影| 欧美成人dvd在线视频| 中文在线资源观看视频网站免费不卡| 国产精品视频网站| 美日韩在线观看| 亚洲午夜久久久久久久久电影院| 久久久视频精品| 中文国产成人精品久久一| 国产精品美女久久久久久久| 久久久一本精品99久久精品66| 亚洲精品在线观看视频| 久久天天躁狠狠躁夜夜av| 一本色道久久综合亚洲二区三区| 国产一区观看| 国产精品不卡在线| 欧美成人日本| 久久国产一区二区| 亚洲视频一区在线观看| 欧美激情网友自拍| 久久亚洲精品中文字幕冲田杏梨 | 欧美在线www| 一区二区三区免费网站| 在线看一区二区| 国产麻豆精品theporn| 欧美国产日韩视频| 久久国产欧美日韩精品| 在线综合欧美| 亚洲国产一区二区a毛片| 久久五月天婷婷| 久久久.com| 午夜精品久久久久久久久久久久久 | 国产精品99久久久久久宅男| 亚洲福利小视频|