C++ 及 Windows 的异常处理(try catch; __try __except; __try __finally)

来源:互联网 发布:商品分类页面设计源码 编辑:程序博客网 时间:2024/06/11 15:23

  • C++ 异常处理:try,catch
try{    // 可能出错的语句, 如果有错,就 throw ...    // 初始化一个异常对象(exception object)}catch( 类型名 [形参名] )    // 异常说明符(exception specifier){    // do 异常处理}catch( 类型名 [形参名] ){    // do 异常处理}

C++ 的异常处理很简单,就是如上的三个关键字,注意 C++ 中 throw,catch 之后没有 Java 等语言中的 finally。

Q: 为何C++不提供“finally”结构? 
A: 因为C++提供了另一种机制,完全可以取代finally,而且这种机制几乎总要比finally工作得更好:“分配资源即初始化”。
(见《The C++ Programming Language》14.4节)基本的想法是,用一个局部对象来封装一个资源,这样一来局部对象的析构函数就可以自动释放资源。这样,程序员就不会“忘记释放资源”了。

  • Windows SEH 异常处理:__try, __except
它们是 Windows 系列操作系统平台上提供的 SEH 模型,也就是说在 C++ 中调用的时候,其实是调用 Windows 的 API。
SEH,又称结构化异常处理,是设计 Windows 操作系统时提出一个种处理异常的方法。这组异常处理机制和 C++ 的很相像,只是关键字是 except 而不是catch。


catch 和 except 的一点不同: 
catch 关键字后面往往好像接受一个函数参数一样,可以是各种类型的异常数据对象;但是 __except 关键字则不同,它后面跟的却是一个表达式(可以是各种类型的表达式)。


小结

(1) C++ 异常模型用 try catch 语法定义,而 SEH 异常模型则用 __try __except 语法;
(2) 与 C++ 异常模型相似,__try __except 也支持多层的 __try __except 嵌套。
(3) 与 C++ 异常模型不同的是,__try __except 模型中,一个 __try 块只能是有一个 __except 块;而 C++ 异常模型中,一个 try 块可以有多个 catch 块。
(4) 与 C++ 异常模型相似,__try __except 模型中,查找搜索异常模块的规则也是逐级向上进行的。但是稍有区别的是,C++ 异常模型是按照异常对象的类型来进行匹配查找的;而 __try __except 模型则不同,它通过一个表达式的值来进行判断。如果表达式的值为1(EXCEPTION_EXECUTE_HANDLER),表示找到了异常处理模块;如果值为0(EXCEPTION_CONTINUE_SEARCH),表示继续向上一层的 __try __except 域中继续查找其它可能匹配的异常处理模块;如果值为-1(EXCEPTION_CONTINUE_EXECUTION),表示忽略这个异常,注意这个值一般很少用,因为它很容易导致程序难以预测的结果,例如,死循环,甚至导致程序的崩溃等。
(5) __except 关键字后面跟的表达式,它可以是各种类型的表达式,例如,它可以是一个函数调用,或是一个条件表达式,或是一个逗号表达式,或干脆就是一个整型常量等等。最常用的是一个函数表达式,并且通过利用 GetExceptionCode() 或 GetExceptionInformation() 函数来获取当前的异常错误信息,便于程序员有效控制异常错误的分类处理。
(6) SEH 异常处理模型中,异常被划分为两大类:系统异常和软件异常。其中软件异常通过 RaiseException() 函数抛出。RaiseException( )函数的作用类似于 C++ 异常模型中的 throw 语句。

详细的请参看:http://www.cnblogs.com/wenziqi/archive/2010/08/26/1809074.html


  • Windows SEH 异常处理:__try, __finally

__try __finally 语句的语法与 __try __except 很类似,稍有不同的是,__finally 后面没有一个表达式,这是因为 __try __finally 语句的作用不是用于异常处理,所以它不需要一个表达式来判断当前异常错误的种类。另外,与 __try __except 语句类似,__try __finally 也可以是多层嵌套的,并且一个函数内可以有多个 __try __finally 语句,不管它是嵌套的,或是平行的。当然,__try __finally 多层嵌套也可以是跨函数的。


最关键的一点:“不管在何种情况下,在离开当前的作用域时,__finally 块区域内的代码都将会被执行到”。


小结

__finally 块被执行的流程时,无外乎三种情况:

(1) 顺序执行到 __finally 块区域内的代码,这种情况很简单,容易理解;
(2) goto 语句或 return 语句引发的程序控制流离开当前 __try 块作用域时,系统自动完成对 __finally 块代码的调用;
(3) 由于在 __try 块中出现异常时,导致程序控制流离开当前 __try 块作用域,这种情况下也是由系统自动完成对 __finally 块的调用。

无论是第 2 种,还是第 3 种情况,毫无疑问,它们都会引起很大的系统开销,编译器在编译此类程序代码时,它会为这两种情况准备很多的额外代码。
一般第 2 种情况,被称为“局部展开(LocalUnwinding)”;第3种情况,被称为“全局展开(GlobalUnwinding)”。
第 3 种情况,也即由于出现异常而导致的“全局展开”,对于程序员而言,这也许是无法避免的,因为在利用异常处理机制提高程序可靠健壮性的同时,不可避免的会引起性能上其它的一些开销。有得必有失。



备注:本文转载自:http://www.cppblog.com/yehao/articles/165099.html


	
				
		
原创粉丝点击