在windows SEH机制注释(1) 基于ReactOS 一文中,注释了try/except宏,windows的SEH机制除了这对宏,还有try/finall宏,用来执行善后处理。相比try/except,try/finall简单很多,没有绕人的长跳转,基本上属于顺序处理流程。如下:
1.
func()
{
_SEH_TRY
{
//do sth
_asm int 0x03;
}
_SEH_FINALLY(FINALLY_)
{
status = _SEH_GetExceptionCode();
}
_SEH_END
}
2.宏扩展
func()
{
for(;;)
{
_SEH_INIT_CONST int _SEHTopTryLevel = (_SEHScopeKind != 0);
_SEHPortableFrame_t * const _SEHCurPortableFrame = _SEHPortableFrame;
_SEHPortableTryLevel_t * const _SEHPrevPortableTryLevel = _SEHPortableTryLevel;
{
_SEH_INIT_CONST int _SEHScopeKind = 0;
register int _SEHState = 0;
register int _SEHHandle = 0;
_SEHFrame_t _SEHFrame;
_SEHTryLevel_t _SEHTryLevel;
_SEHPortableFrame_t * const _SEHPortableFrame =
_SEHTopTryLevel ? &_SEHFrame.SEH_Header : _SEHCurPortableFrame;
_SEHPortableTryLevel_t * const _SEHPortableTryLevel = &_SEHTryLevel.ST_Header;
(void)_SEHScopeKind;
(void)_SEHPortableFrame;
(void)_SEHPortableTryLevel;
(void)_SEHHandle;
for(;;)
{
if(_SEHState)
/*
初始时_SEHState为0,进入SEH_FINALL!else分支,设置SEH处理结构__SEHTryLevel
*/
{
for(;;)
{
{
<-try/
{
//(1)
//do sth,如果发生异常,没有跳转,确切的说是由系统在fs:[0]中查找上一层堆栈中提供的处理函数
//如果没有发生异常,顺序的执行到(2)处,执行善后处理
_asm int 0x03;
}
finall ->/
}
break;
}
_SEHPortableFrame->SPF_TopTryLevel = _SEHPrevPortableTryLevel;
break;
}
else
{
_SEHTryLevel.ST_Header.SPT_Handlers.SH_Filter = 0;
/*
FINALLY_由_SEH_FINALLY(FINALLY_)传入,设置收尾函数
*/
_SEHTryLevel.ST_Header.SPT_Handlers.SH_Finally = (FINALLY_);
_SEHTryLevel.ST_Header.SPT_Next = _SEHPrevPortableTryLevel;
_SEHFrame.SEH_Header.SPF_TopTryLevel = &_SEHTryLevel.ST_Header;
if(_SEHTopTryLevel)
{
if(&_SEHLocals != _SEHDummyLocals)
_SEHFrame.SEH_Locals = &_SEHLocals;
_SEH_EnableTracing(_SEH_DO_DEFAULT_TRACING);
_SEHFrame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler;
_SEHEnterFrame(&_SEHFrame.SEH_Header);
}
/*
经过++ _SEHState;
continue;
程序进入if(_SEHState),执行受保护的代码(其实不算受保护的代码,与
SEH_Except相比少了长跳转)
*/
++ _SEHState;
continue;
}
//(2)
break;
}
// _SEH_FINALLY(FINALLY_)
/*
执行这个回调有2种可能
1.执行完(1)后,一路break出来,执行善后函数或者
2.执行(1)时遇到异常,进入异常处理过程。期间执行unwind时会调用
(SEHTryLevel.ST_Header.SPT_Handlers.SH_Finally)(&_SEHFrame.SEH_Header);
*/
(FINALLY_)(&_SEHFrame.SEH_Header);
if(0)
{
//
{
status = _SEH_GetExceptionCode();
}
//
}
}
if(_SEHTopTryLevel)
_SEHLeaveFrame();
break;
}
}