主要參考:http://blog.csdn.net/hbrr224/archive/2006/05.aspx
SEH 的工作原理。
???????? Windows 程序設計中最重要的理念就是消息傳遞,事件驅動。當GUI應用程序觸發一個消息時,系統將把該消息放入消息隊列,然后去查找并調用窗體的消息處理函數(CALLBACK),傳遞的參數當然就是這個消息。我們同樣可以把異常也當作是一種消息,應用程序發生異常時就觸發了該消息并告知系統。系統接收后同樣會找它的“回調函數”,也就是我們的異常處理例程。當然,如果我們在程序中沒有做異常處理的話,系統也不會置之不理,它將彈出我們常見的應用程序錯誤框,然后結束該程序。所以,當我們改變思維方式,以CALLBACK 的思想來看待 SEH,SEH 將不再神秘。
SEH 是 Windows 系統提供的功能,跟開發工具無關。值得一提的是,VC 將 SEH 進行了封裝 try? catch? finally,c++中也可以用c的封裝 __try{}__except(){} 和 __try{}__finally{}. 所以當你建立一個C++ try塊時,編譯器就生成一個S E H_ _t r y塊。一個C + +c a t c h測試變成一個S E H異常過濾器,并且c a t c h中的代碼變成S E H_ _e x c e p t塊中的代碼。實際上,當你寫一條C++ throw語句時,編譯器就生成一個對Wi n d o w s的R a i s e E x c e p t i o n函數的調用。用于t h r o w語句的變量傳遞給R a i s e E x c e p t i o n作為附加的參數。
一個簡單的使用SEH的例子
假如要實現一個完全強壯的應用程序,該程序需要每周7天,每天2 4小時運行。在今天的世界里,軟件變得這么復雜,有那么多的變量和因子來影響程序的性能,筆者認為如果不用S E H,要實現完全強壯的應用程序簡直是不可能的。我們先來看一個樣板程序,即C的運行時函數s t r c p y:
char
*
?strcpy(
???
char
*
?strDestination,
???
const
?
char
*
?strSource);
這是一個相當簡單的函數,它怎么會引起一個進程結束呢?如果調用者對這些參數中的某一個傳遞N U L L(或任何無效的地址),s t r c p y就引起一個存取異常,并且導致整個進程結束。
使用S E H,就可以建立一個完全強壯的s t r c p y函數:
char
*
?RobustStrCpy(
char
*
?strDestination,?
const
?
char
*
?strSource)

{
???__try?

???
{
??????strcpy(strDestination,?strSource);
???}
???__except(EXCEPTION_EXECUTE_HANDLER)

???
{
??????
//
?Nothing?to?do?here
???}
???
return
(strDestination);
}
這個函數所做的一切就是將對s t r c p y的調用置于一個結構化的異常處理框架中。如果s t r c p y執行成功,函數就返回。如果s t r c p y引起一個存取異常,異常過濾器返回E X C E P T I O N _E X E C U T E _ H A N D L E R,導致該線程執行異常處理程序代碼。在這個函數中,處理程序代碼什么也不做,R o b u s t S t r C p y只是返回到它的調用者,根本不會造成進程結束。
另一個使用:
#include?
"
stdio.h
"
void
?test()

{
int
*
?p?
=
?
0x00000000
;?
//
?pointer?to?NULL
__try

{
puts(
"
in?try
"
);
__try

{
puts(
"
in?try
"
);

//
?causes?an?access?violation?exception;
//
?導致一個存儲異常
*
p?
=
?
13
;?

//
?呵呵,注意這條語句
puts(
"
這里不會被執行到
"
);
}
__finally

{
puts(
"
in?finally
"
);
}
//
?呵呵,注意這條語句
puts(
"
這里也不會被執行到
"
);
}
__except(puts(
"
in?filter?1
"
),?
0
)

{
puts(
"
in?except?1
"
);
}
}
void
?main()

{
puts(
"
hello
"
);
__try

{
test();
}
__except(puts(
"
in?filter?2
"
),?
1
)

{
puts(
"
in?except?2
"
);
}
puts(
"
world
"
);
}
?
上面的程序運行結果如下:
hello
in try
in try
in filter 1
in filter 2
in finally
in except 2
world
Press any key to continue
另一個混合c++的異常處理使用:
// 注意,這是 C++ 程序,文件名為: SEH-test.cpp
#include?
"
stdio.h
"
?

class
?A?


{?

public
:?


void
?f1()?
{}
?

//
?拋出?C++?異常?
void
?f2()?
{?
throw
?
888
;}
?

}
;?

//
?這個函數中使用了?try-catch?處理異常,也即?C++?異常處理?
void
?test1()?


{?

A?a1;?

A?a2,a3;?

try
?


{?

a2.f1();?

a3.f2();?

}
?

catch
(
int
?errorcode)?


{?

printf(
"
catch?exception,error?code:%d\n
"
,?errorcode);?

}
?

}
?

//
?這個函數沒什么改變,仍然采用?try-except?異常機制,也即?SEH?機制?
void
?test()?


{?

int
*
?p?
=
?
0x00000000
;?
//
?pointer?to?NULL?
__try?


{?

//
?這里調用?test1?函數?
test1();?

puts(
"
in?try
"
);?

__try?


{?

puts(
"
in?try
"
);?

//
?causes?an?access?violation?exception;?

//
?導致一個存儲異常?
*
p?
=
?
13
;?

puts(
"
?這里不會被執行到?
"
);?

}
?

__finally?


{?

puts(
"
in?finally
"
);?

}
?

puts(
"
?這里也不會被執行到?
"
);?

}
?

__except(puts(
"
in?filter?1
"
),?
0
)?


{?

puts(
"
in?except?1
"
);?

}
?

}
?

void
?main()?


{?

puts(
"
hello
"
);?

__try?


{?

test();?

}
?

__except(puts(
"
in?filter?2
"
),?
1
)?


{?

puts(
"
in?except?2
"
);?

}
?

puts(
"
world
"
);?

}
?

上面程序不僅能夠被編譯通過,而且運行結果也是正確的(和預期的一樣,同樣符合 C++ 異常處理模型的規則,和 SEH 異常模型的處理規則)。其結果如下:
hello
catch exception,error code:888
in try
in try
in filter 1
in filter 2
in finally
in except 2
world
Press any key to continue
主要參考:http://blog.csdn.net/hbrr224/archive/2006/05.aspx