异常处理第三讲,SEH(结构化异常处理),异常展开问题
异常处理第三讲,SEH(结构化异常处理),异常展开问题
作者:IBinary
出处:http://www.cnblogs.com/iBinary/
版权所有,欢迎保留原文链接进行转载:)
不知道昨天有木有小伙伴尝试写一下SEH异常处理的代码.如果没写过,请回去写( :) 不写也没关系 ( ̄┰ ̄*))
那么说下昨天的异常处理的问题
一丶昨天代码问题所在
请看下昨天的代码
// SEHecpt.cpp : Defines the entry point for the console application.
// #include "stdafx.h"
#include <WINDOWS.H>
#include <STDLIB.H>
#include <WINNT.H> void fun2(); EXCEPTION_DISPOSITION __cdecl HANDLER1(
struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * DispatcherContext)
{ MessageBox(NULL,"我处理了异常\r\n",NULL,NULL);
return ExceptionContinueSearch;
}
void fun1()
{
__asm
{ push offset HANDLER1
push fs:[]
mov fs:[],esp
} fun2();
char *p = NULL;
*p = ;
__asm
{
pop fs:[]
add esp,
ret
}
}
void fun2()
{
char *p =NULL;
*p = ;
} int main(int argc, char* argv[])
{ fun1();
system("pause"); }
上图代码则是我们昨天的代码,我们编译,链接,并且运行一下.
第一次:

当我们点击异常确定

程序会显示退出,因为我们的返回这设置的是继续搜索,也就是我不处理了,交给上一层处理,而上一层是操作系统
我们点击关闭程序

这个时候,我们的回调又被操作系统掉了一次,第二次来的时候的标志是2,具体的可以通过输出参数查看.
最后点击确定我们的程序才退出了.
那么我们不觉着奇怪吗,为什么操作系统会第二次调用了一次我们的回调函数?
原因是操作系统正在进行异常展开,调用我们的回调是告诉我们,该处理的处理.
二丶什么是异常展开
上面我们说了异常展开,也把我们的代码贴出来了.那么现在思考一个问题
当 fun1函数调用fun2函数
的时候,fun2函数也注册一个SEH筛选器异常,(注册相当于往链表头插入)
例如下面的代码
void fun1()
{
__asm
{ push offset HANDLER1
push fs:[]
mov fs:[],esp
} fun2();
char *p = NULL;
*p = ;
__asm
{
pop fs:[]
add esp,
ret
}
}
void fun2()
{
__asm
{
push offset HANDLER2 //注册回调函数
push fs:[] //压入旧的链表指针
mov fs:[],esp //新的位置变成当前的SEH
}
char *p =NULL;
*p = ;
//取消注册,和上面一样,不写了,为了节省空间
}
那么我们知道,现在的链表头是Fun2,也就是 Fun2链表中的next位置指向了Fun1的位置,回调函数也是fun2的
那么我们现在想想,如果fun2出现了异常,而fun2的回调函数是处理不了这个异常的,那么会交给fun1去处理
这个没问题吧,但是你想,fun2交给fun1处理的时候,取消注册是不可能在执行了.
也就是说,现在的fun2 是链表头,并没有断开连接,或者卸载这个函数,那么如果这个时候fun1出现了问题怎么办?
操作系统当出现异常的时候,会依次遍历这个链表,此时的Fun2已经是无效的了,我们并不能让它去调用.而是应该把异常的链表的首地址,重置为当前的fun1所在的位置.
看下图:

那么这种操作,就叫做异常展开,简单来说就是 fun1 调用fun2 fun2出现了异常,自己的异常链表来不及卸载,此时只能交给fun1去处理,那么现在我们应该把链表的位置重置为fun1的异常链表,fun2的不在需要了.否则操作系统调用的时候则是调用了一个错误的地址.
说到释放的时候我们上面说了,操作系统会根据错误标志2,来接着调用一次我们的异常回调函数,这就是因为在操作系统帮我们卸载这个异常链表,但是会依次的调用一次我们的回调函数,通知我们,该释放资源的释放资源,该处理的处理,给我们一次释放资源的机会.
三丶异常处理的顺序
异常处理处理发生的时候,会有顺序的
1.系统首先发送给调试器 调试器优先级最高
2.如果没有调试器,系统会继续查找线程相关的异常处理,
3.每个线程相关的异常处理例程,可以处理或者不处理这个异常,如果不处理,并且安装了多个线程相关的处理例程,可交给连起来的其它例程处理
4.不处理这个异常,在判断程序是否在调试状态,如果在就接着给调试器
5.如果没有的话,或者不处理,那么操作系统就会调用筛选器异常
6.如果没有,那么系统会调用默认的异常处理,也就是崩溃的的界面
7.在终结之前,对其展开操作,然后依次调用设置的SEH链表中的回调函数,给予一次最后清理的机会.
四丶主动引发异常
我们说过throw这个语句会抛出一个异常,其实底层调用的也是API
void RaiseException(DWORD dwExeptionCode,
DWORD dwExceptionFlages
DWORD nNumberOfArguments,
Const DWORD * lpArguments
前两个分别是退出代码,和错误标志,这个在筛选器异常已经讲过了
最后两个参数是用户自定义的.throw这个语法就是调用的这个API
五丶自动展开操作
我们说过,异常展开的时候,我们自己也可以去做,也可以交给操作系统做,而操作系统做的时候也是调用的API
RtIUnwind 具体可以查询下MSDN.想了解底层自己查询一下,不多做讲解.
关于可处理异常,以及异常的第二个参数的应用,明天讲解,怕一下 讲解太多
作者:IBinary
出处:http://www.cnblogs.com/iBinary/
版权所有,欢迎保留原文链接进行转载:)

异常处理第三讲,SEH(结构化异常处理),异常展开问题的更多相关文章
- 第23章 SEH结构化异常处理(2)_编译器对系统SEH机制的封装
23.2 编译器层面对系统SEH机制的封装 23.2.1 扩展的EXCEPTION_REGISTRATION级相关结构:VC_EXCEPTION_REGISTRATION (1)VC_EXCEPTIO ...
- 第23章 SEH结构化异常处理(1)_系统SEH机制
23.1 基础知识 23.1.1 Windows下的软件异常 (1)中断和异常 ①中断是由外部硬件设备或异步事件产生的 ②异常是由内部事件产生的,可分为故障.陷阱和终止三类. (2)两种异常处理机制: ...
- 第25章 SEH结构化异常处理_未处理异常及向量化异常
25.1 UnhandledExceptionFilter函数详解 25.1.1 BaseProcessStart伪代码(Kernel32内部) void BaseProcessStart(PVOID ...
- 第24章 SEH结构化异常处理_异常处理及软件异常
24.1 程序的结构 (1)try/except框架 __try{ //被保护的代码块 …… } __except(except fileter/*异常过滤程序*/){ //异常处理程序 } (2) ...
- Windows内核读书笔记——SEH结构化异常处理
SEH是对windows系统中的异常分发和处理机制的总称,其实现分布在很多不同的模块中. SEH提供了终结处理和异常处理两种功能. 终结处理保证终结处理块中的程序一定会被执行 __try { //要保 ...
- 第23章 SEH结构化异常处理(3)_终止处理程序
23.3 终止处理程序 23.3.1 程序的结构 (1)框架 __try{ //被保护的代码块 …… } __finally{ //终止处理 } (2)__try/__finally的特点 ①fina ...
- 深入研究 Win32 结构化异常处理(作者博客有许多SEH的研究文章)
摘要 就像人们常说的那样,Win32 结构化异常处理(SEH)是一个操作系统提供的服务.你能找到的所有关于 SEH 的文档讲的都是针对某个特定编译器的.建立在操作系统层之上的封装库.我将从 SEH 的 ...
- [C++]深入解析结构化异常处理(SEH)
http://www.cppblog.com/weiym/archive/2015/02/27/209884.html 尽管以前写过一篇SEH相关的文章<关于SEH的简单总结>, 但那真的 ...
- SEH:结构化异常处理 学习
SEH:结构化异常处理 结构化异常处理机制提供了一个操作系统,用于优化结构的方案,为客户提供更强大的程序执行环境.试想一下,你写程序不用考虑内存访问错误,那里是空指针错误,一直在按照程序的逻辑结构来写 ...
随机推荐
- Coursera上视频无法播放将怎么解决?
相信很多朋友在播放Coursera中的视频都会遇到一个问题,视频全黑,点击播放,进度条转了一圈又消失不见. 这时候我们该找找是什么问题啦? 解决方法一: 如果你是FQ看的网课视频,那么你把VPN从au ...
- Android: Only the original thread that created a view hierarchy can touch its views 异常
最近自己再写一个小项目练手,创建一个线程从网络获取数据然后显示在 recyclerView 上.写好后发现页面能够显示,但是有时候会把请求的数据显示过来,有时候不会.点开 android monito ...
- sass学习--安装ruby
1.下载ruby:https://rubyinstaller.org/downloads/ 2.安装完ruby之后,在开始菜单中,找到刚才我们安装的ruby,打开Start Command Promp ...
- python3.0 模拟用户登录,三次错误锁定
# -*- coding:utf-8 -*- #需求模拟用户登录,超过三次错误锁定不允许登陆 count = 0 #realname passwd Real_Username = &quo ...
- 如何让只支持IE浏览器的jsp转为可以支持chrome
如果你的项目只能使用IE浏览器打开,你想让其支持chrome的话,可以试一下下面的代码哦: function showLayerDialog(url,paramFuction){ top.layer. ...
- 基于gitHub+hexo搭建的个人博客
文章导航 前期准备 安装hexo 修改hexo主题 自定义主题 部署本地文件到github查看 我的第一篇博客 前期准备 下载安装git命令行工具.node及npm环境 注册自己的GitHub账号 安 ...
- 史上最全的IntelliJIdea快捷键
Ctrl+Shift+方向键Up/Down 代码向上/下移动. Ctrl+X 删除行 Ctrl+Y 也是删除行,不知道有啥区别 Ctrl+D 复制行 Ctrl+Alt+L 格式化代码 Ctrl+N 查 ...
- CSS3属性——“box-flex”
CSS3的新增属性有很多,其中有一个比较神奇的,通常称为盒子模型布局,不需要把div浮动,也能合理分配.看如下例子: HTML: <div id="box"> < ...
- Struts2-整理笔记(三)结果处理跳转、获得servletAPI原生
在struts2中有很多种跳转方式如下是在struts-default.xml截取的一段源码,常用的跳转有 转发:dispatcher.重定向:redirect.转发到Action:chain.重定向 ...
- K-Means和图片压缩
通俗的介绍这种压缩方式,就是将原来很多的颜色用少量的颜色去表示,这样就可以减小图片大小了.下面首先我先介绍下K-Means,当你了解了K-Means那么你也很容易的可以去理解图片压缩了,最后附上图片压 ...