不捕捉某一个异常

常常有这种情况,代码不需要捕捉异常,但需要执行一些清理或者修正操作。虽然不总是,支持物(holders)经常用在这种场景里。在支持物(holders)不适用的情况里,CLR提供了两个“finally”块的变种。

EX_TRY_FOR_FINALLY

当需要在代码退出时执行修正操作时,一个finally块就比较合适。在CLR里有一系列的宏来实现try/finally:

EX_TRY_FOR_FINALLY
// code
EX_FINALLY
// exit and/or backout code
EX_END_FINALLY
注意:EX_TRY_FOR_FINALLY是基于SEH(Windows操作系统异常处理机制),而不是C++的异常处理机制。C++编译器不允许在一个函数里混合使用SEH和C++异常处理机制。有自动析构函数的局部变量要求C++异常处理机制以执行其析构函数。因此,使用了EX_TRY_FOR_FINALLY宏的函数不能同时使用EX_TRY,也不能有使用了自动析构函数的局部变量。

EX_HOOK

经常有这种情况,只在某种异常抛出的时候需要执行修正代码。对这些情况,EX_HOOK跟EX_FINALLY很类似,但是“勾子(hook)”子句只在有异常的时候执行。异常会自动在退出“勾子”子句之前再次抛出。

EX_TRY
// code
EX_HOOK
// code to run when an exception escapes the “code” block.
EX_END_HOOK

这个结构比简单的EX_CATCH配上EX_RETHROW块更好一些,因为其可以捕捉堆栈溢出异常(并向上展开堆栈),并再次抛出一个新的堆栈溢出异常。

抛出异常

在CLR里抛出异常其实就是下面的函数调用:

COMPlusThrow ( < args > )

有很多重载函数,但思路基本上就是向COMPlusThrow传入某个异常作为参数。异常类型由Rexcep.h中的一系列宏生成,如kAmbiguousMatchException, kApplicationException等类型。(重载函数)的其他参数指定资源和替代性文字。可以参考报告了类似异常的代码来选择异常类型。

以下是一些预定义的异常变种:

COMPlusThrowOOM();

最终调用ThrowOutOfMemory()函数,其抛出C++的OOM(内存不足)异常。它抛出一个预先创建的异常,因为不能在内存不足的情况下再找出内存创建这个异常!

当获取这个异常对应的托管异常时,CLR首先会尝试分配一个新托管对象[1],如果失败的话,那么就返回一个预先分配的,全局共享的内存不足异常对象。

[1] 毕竟,如果申请分配2G大小的数组失败,申请一个小对象还是可以试试的。

COMPlusThrowHR(HRESULT 问题HR);

如果你有IErrorInfo的话,有很多重载可用。还有一些惊人复杂的代码来指出一个HRESULT值对应哪种异常:

COMPlusThrowWin32(); / COMPlusThrowWin32(hr);

基本上是从Win32错误返回值抛出异常:HRESULT_FROM_WIN32(GetLastError())

COMPlusThrowSO();

抛出一个堆栈溢出(SO)异常。注意这个不是一个硬性的堆栈溢出,只是在可能导致硬性堆栈溢出的时候抛出的异常。

跟内存不足异常(OOM)类似,其抛出一个预先分配的C++堆栈溢出异常。跟OOM不同,当获取托管异常对象时,CLR总是返回预先分配的,全局共享的堆栈溢出异常对象。

COMPlusThrowArgumentNull()

抛出“参数不能为空”异常的辅助函数。

COMPlusThrowArgumentOutOfRange()

如名所示。

COMPlusThrowArgumentException()

另一个无效参数相关的异常。

COMPlusThrowInvalidCastException(thFrom, thTo)

传入强制转换的源类型和目的类型,这个函数可以返回一个相当不错的异常消息。

EX_THROW

这个是非常底层的抛出异常的函数,普通代码基本不用。很多COMPlusThrowXXX函数在内部使用EX_THROW,跟其它特定的ThrowXXX函数类似。最好少用EX_THROW,尽量使用封装好的函数以隐藏异常机制的细节。当然,如果没有合适的Throw函数可用,使用EX_THROW是可以接受的。

这个宏接受两个参数,要抛出的异常类型(C++ Exception类的某些子类),和用括号括起来的传递给该类型异常的构造函数的参数列表。

作者:懿民
链接:https://www.jianshu.com/p/a235f2ea6be1
来源:简书

最新文章

  1. win8改win7笔记
  2. PHP foreach使用
  3. UESTC 2016 Summer Training #6 Div.2
  4. SQL 获取各表记录数的最快方法
  5. Linux基础教程之/dev/null和/dev/zero的区别及其用法
  6. IC卡写卡操作流程
  7. 动态链接库中分配内存引起的问题-- windows已在XX.exe中触发一个断点
  8. [置顶] ※数据结构※→☆线性表结构(queue)☆============队列 顺序存储结构(queue sequence)(八)
  9. 重写ArcGIS的TiledMapServiceLayer呼叫世界地图图块
  10. 客户端程序通过TCP通信传送&quot;小文件&quot;到服务器
  11. HDU 4062 Partition
  12. GlusterFS缺点分析[转]
  13. 菜单栏-Place(放置)菜单
  14. Spark学习之路 (二十八)分布式图计算系统
  15. stark组件前戏之项目启动前加载指定文件
  16. NESTED最终与外部事务合并在一起提交
  17. 升级到yosemite后homebrew报错的解决
  18. ios开发之--UITableView中的visibleCells的用法
  19. spring mvc leaning
  20. 上手并过渡到PHP7(5)——轻量级“集合”迭代器-Generator

热门文章

  1. 6. 运行Spark SQL CLI
  2. 《Effective Objective-C》概念篇
  3. sqlserver通过递归查找所有下级或上级部门和用户的操作实例
  4. redis-集群(codis和Cluster)
  5. Mysql表字段命令alter add
  6. Entity Framework Codefirst的配置步骤
  7. 如何定位 golang 进程 hang 死的 bug
  8. Django 信号使用问题
  9. canvas教程(一) 简介
  10. 基于TCP通过socketserver简单实现并发效果