异常和中断是程序运行时比较重要的2个概念, 异常通常是由程序内部引起的(比较常见的如堆栈溢出, 空指针访问等),中断通常是由外部系统引起的, 外部产生的中断在应用程序中很多时候会以事件或回调的方式通知出来(比如常见的IO事件)。

Windows上应用程序的异常处理是以SEH(structure exception handler)的方式提供的, 关于SEH的实现原理,这里有篇不错的文章可以参考《栈溢出中利用SEH》。

关于SEH的使用,主要包括终止处理(finally)和异常处理(exception).

(1)终止处理主要是由编译器实现的,比如下面代码
__try
{
...
__leave
...
}
__finally
{
...
}
无论是你在try块中过早的return还是在try中发生了异常, 编译器都会确保在任何情况下你的终止处理(finally)代码都能得到执行。

(2)异常处理主要是由操作系统来实现的, 比如下面代码
__try
{
...
}
__except(filter function)
{
...
}
其中filter function可返回以下类型:
EXCEPTION_EXECUTE_HANDLER: 这是告诉系统, 我认识这个异常,请执行我的异常处理代码,然后从接下来的第一行代码开始继续执行 
EXCEPTION_CONTINUE_SEARCH: 这个是告诉系统, 我不认识这个异常, 请继续往外抛异常
EXCEPTION_CONTINUE_EXECUTE: 这个是告诉系统, 我已经在调用filter时修正了这个异常, 请从发生异常的地方继续执行

如何知道当前程序发生了哪种类型的异常? 系统提供了2个接口:GetExceptionCode  GetExceptionInformation 
比如我们常见的exception code包括:EXCEPTION_ACCESS_VIOLATION, EXCEPTION_STACK_OVERFLOW,EXCEPTION_INT_DIVIDE_BY_ZERO

上面的几种异常都是硬件异常,是由CPU在运行过程中引发的, 还有一些异常是软件异常,是我们通过调用系统API RaiseException引发的。
我们知道C++的异常处理大概是这样的:
try
{
...
}
catch(int a)
{
...
}
catch(...)
{
...
}
思考C++异常和结构化异常(SEH)是 什么关系? 
实际C++异常是通过结构化异常中的软件异常实现的, 也就是通过调用RaiseException实现的, 通过测试我们可以发现VC编译器C++异常的异常号永远是0xE06D7363,对应ASCII码“.msc".
posted on 2014-09-19 21:00 Richard Wei 阅读(3997) 评论(3)  编辑 收藏 引用

FeedBack:
# re: 关于SEH的简单总结[未登录]
2014-09-22 12:58 | cc
博主,你好,我本来是想改用C++的try catch (...) 捕获所有异常
try
{
int y = 0;
int x = 5/y;
cout << "y = " << y << endl;
}
catch (...)
{
cout << "Throw a Exception..." << endl;
}
但发现,上面的代码,根本就捕获不到,也就是cout << "Throw a Exception..." << endl;
这条语句,根本就不会输出。

运行环境VC2012 + Windows 7

博主,你那边有这种情况吗?

这是我的那篇文章的地址
http://blog.csdn.net/cocoasprite/article/details/39289577  回复  更多评论
  
# re: 关于SEH的简单总结
2014-09-22 13:18 | Richard Wei
@cc
本来就是, C++异常只能捕获软件异常, 硬件异常(如除零,空指针访问)用操作系统的SEH捕获。  回复  更多评论
  
# re: 关于SEH的简单总结[未登录]
2014-09-22 13:36 | cc
嗯,受教了,谢谢!@Richard Wei
  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理