首页
社区
课程
招聘
[原创]白话windows之四 异常处理机制(VEH、SEH、TopLevelEH...)
发表于: 2013-6-19 01:41 38081

[原创]白话windows之四 异常处理机制(VEH、SEH、TopLevelEH...)

2013-6-19 01:41
38081

今天是我侄子的4岁生日,特此更新一篇,祝我小侄子在幼儿园多泡MM

我们都知道SEH异常处理机制,那VEH、TopLevelEH呢?他们执行的先后顺序是怎样的呢?当这些机制都不使用的情况下,会发生什么情况呢?异常处理器是怎么工作的?如果你对此感兴趣,那我们就一起来扒开异常处理机制的面纱吧

术语:
SEH: 结构化异常处理
VEH: 向量化异常处理
TopLevelEH:顶层异常处理

EXCEPTION_EXECUTE_HANDLER :该异常被处理。从异常处下一条指令继续执行
EXCEPTION_CONTINUE_SEARCH:不能处理该异常,让别人处理它吧
EXCEPTION_CONTINUE_EXECUTION:该异常被忽略。从异常处处继续执行

//调试器返回值:
DBG_CONTINUE : 等同于EXCEPTION_CONTINUE_EXECUTION
DBG_EXCEPTION_NOT_HANDLED :等同于EXCEPTION_CONTINUE_SEARCH


想想对我这等语文是体育老师教出来的童鞋来说,想把这个主题将透彻,还真是有点难度的~,我们还是按异常处理器执行顺序来吧,废话不多说,开始。。。

异常处理器其实包含 内核异常处理R3异常处理内核异常处理比较简单,我也对它没兴趣,所以这里就把它给忽略了。我们只讲R3程序产生异常时,异常处理器是怎么工作的。

异常处理器处理顺序流程
1. 交给调试器(进程必须被调试)
2. 执行VEH
3. 执行SEH
4. TopLevelEH(进程被调试时不会被执行)
5. 交给调试器(上面的异常处理都说处理不了,就再次交给调试器)
6. 调用异常端口通知csrss.exe


大致分上面几步把,下面咱就详细讨论一下各个步骤都干了哪些细活

1. 第一次交给调试器
如果该出现异常的程序正在被调试,则该异常首先交给调试器处理(通过DebugPort)。
调试器拿到这个异常后,需要判断是否要处理该异常,如果处理该异常返回DBG_CONTINUE,否则返回DBG_EXCEPTION_NOT_HANDLED

    while(!bExit) 
    {
        DWORD dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
        DEBUG_EVENT debugEvent;
        WaitForDebugEvent(&debugEvent, INFINITE);
        switch ( debugEvent.dwDebugEventCode )
        {
        case EXCEPTION_DEBUG_EVENT:
            {
                EXCEPTION_DEBUG_INFO* pExcpInfo = &debugEvent.u.Exception;
                if ( MessageBox(0,_T("处理该异常?"), _T("我是调试器"),MB_YESNO)==IDYES )
                {
                    dwContinueStatus = DBG_CONTINUE;
                    //...
                }
            }
            break;
            //...
        }
        ContinueDebugEvent(debugEvent.dwProcessId,  debugEvent.dwThreadId, dwContinueStatus); 
    }
LONG NTAPI FirstVectExcepHandler( PEXCEPTION_POINTERS pExcepInfo )
{
    if( ... )
    {
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    return EXCEPTION_CONTINUE_SEARCH;
}
//参数1=1表示插入Veh链的头部,=0表示插入到VEH链的尾部
AddVectoredExceptionHandler( 1, &FirstVectExcepHandler );

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 9
支持
分享
最新回复 (16)
雪    币: 218
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
UnhandledExceptionFilter处理不了还会再一次交给VEH处理,但是这个句柄是用AddVectoredContinueHandler注册的
不过Win7下这个又有了一些变化,详见https://blogs.msdn.com/b/zhanli/archive/2010/06/25/c-tips-addvectoredexceptionhandler-addvectoredcontinuehandler-and-setunhandledexceptionfilter.aspx?Redirected=true
2013-6-19 04:21
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
3
我看了一下AddVectoredContinueHandler,不支持我的Xp32
然后在我的Win8 64位上跑的时候,发现是不起效果的,使用AddVectoredContinueHandler注册的Handler不会被执行。
MSDN上也没说明一下蛋都碎了
2013-6-19 07:27
0
雪    币: 437
活跃值: (78)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
祝你侄子生日快乐
2013-6-19 08:45
0
雪    币: 496
活跃值: (286)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
5
AddVectoredContinueHandler是在Windows XP Professional x64 Edition以及之后的系统中才有。
2013-6-19 09:37
0
雪    币: 6723
活跃值: (1199)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习了,谢谢了
2013-6-19 09:44
0
雪    币: 496
活跃值: (286)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
7
文中有一些基本知识的误区。

LONG FirstSEHer( PEXCEPTION_POINTERS pExcepInfo )
LONG SecondSEHer( PEXCEPTION_POINTERS pExcepInfo )

这些函数只是exception过滤函数,并不是真正的exception hanlder

真正的SEH exception handler 是每一个_try块后面跟随的_except块中的内容。

另外__ finally子句块的内容也是一个很有深度的内容,建议把这块内容也讲出来,最后__finally和_except结合在一起的时候,又会是更有趣的内容。
2013-6-19 09:56
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
8
你说FirstSEHer只是exception过滤函数这个观点我不认同。其实FirstSEHer可以做任何事。反而__except内部可以做的事情就受到限制了,因为只有FirstSEHer返回EXCEPTION_EXECUTE_HANDLER时才会进入__except内。

__try _except __ finally是VC辅助实现的,SEH链的构造和分发过程确实有好多值得学习和借鉴的地方。过段时间打算写一个可以在非VC(gcc、clong等)中使用的SEH框架。

感谢关注
2013-6-19 10:52
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
9
不知道为啥Win8上失效了,WIn7好像也不可以
2013-6-19 10:55
0
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
10
先顶再看
2013-6-19 11:55
0
雪    币: 257
活跃值: (67)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
慢慢看,学习了
2013-6-19 12:15
0
雪    币: 1042
活跃值: (495)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
好文章,学习了~
2013-7-15 14:14
0
雪    币: 108
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
不得不读
2013-7-15 23:49
0
雪    币: 773
活跃值: (442)
能力值: ( LV9,RANK:200 )
在线值:
发帖
回帖
粉丝
14
好文章,学习了~
2013-7-16 05:05
0
雪    币: 50
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
MSDN上有如下说明:
To compile an application that uses this function, define the _WIN32_WINNT macro as 0x0500 or later. For more information, see Using the Windows Headers.

我印象中,较老的编译器编译出来的EXEPE头中,OS Version和Subsystem Version两个成员值都是4.0,也就意味着在Win2K上都能跑。

AddVectoredContinueHandler是XP后才出现的,所以只能支持Win5.1及其以后版本,所以OS Version和Subsystem Version必须大于5.0。

我现在用着Win8 64位,弄弄看是不是这个问题
2014-2-7 16:27
0
雪    币: 50
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
16
我的Win8 64位AddVectoredContinueHandler注册的Handler有效,跑起了,用的是12.0的编译器,OS Version和Subsystem Version两个成员值是6.0。但我把他俩改成4.0,VEH还是有效。。。。纳闷了
2014-2-7 16:31
0
雪    币: 218
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
PE文件头那两个值只在加载时有用,跟执行无关
2014-2-7 22:08
0
游客
登录 | 注册 方可回帖
返回
//