Item 8 防止因异常而离开析构函数

C++在语法上并不禁止从dtor中引发异常。但这在实践中会构成隐患。如下面:

 

 

在某种条件下同时产生两个异常,会导致程序的提前中止,或者引发未定义行为。上例中,如果v的某两个元素在析构时同时产生异常,会引发未定义行为。这是隐患。
在dtor里使用STL中的容器、TR1中的容器、甚至数组,都可能引发未定义行为;即使不用容器/数组,产生异常时也会导致程序提前中止,或引发未定义行为。

在两种情况下会调用dtor。第一种是正常删除一个对象,例如对象超出了作用域或被显式地delete。第二种是在异常传递的stack-unwinding过程中,由异常处理系统删除一个对象。
在上述两种情况下,调用dtor时异常可能处于激活状态也可能没有处于激活状态。遗憾的是没有办法在dtor内部区分出这两种情况。
因此在写dtor时你必须保守地假设"有"异常被激活,因为如果在一个异常被激活的同时,dtor也抛出异常,并导致程序控制权转移到dtor以外,C++将调用terminate函数,立即中止程序。

结论:C++不喜欢会引发异常的dtor。
但是,有时在dtor中进行的操作确实有引发异常的危险。如关闭数据库:

 

 

一般为了确保数据库的连接被关闭,都会用“管理器”在dtor里加个“保险”:

 

 

这样,客户在使用时,即使忘记关闭连接,该操作也会自动进行:

 

 

但是,如果关闭失败,就会引发异常,那么上面在dtor中的“保险”就会把异常传播出去,从而离开了dtor的控制,导致析构不能全部完成。“保险”失效了!

有两种方法控制这种情况。

第一种方法:强行中止程序,以防止未定义行为。

 

 

第二种方法:抑制住所有异常。这样,当异常发生时,还可以在dtor里做一些事情,让程序继续运行。

 

 

表面上catch没有做任何事情,实际上它阻止了任何异常被传递到dtor外面。无论对象是不是在stack unwinding中被释放,terminate函数都不会被调用。

一个更好的办法:重新设计数据库管理器,让客户主动去处理异常。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值