【C++ Exceptions】exception specifications的利与弊、非预期异常的预防与处理

exception specifications利与弊

  • 漂亮的注释;
  • 编译器有时能在编译过程中,检测到与exception specifications不一致的行为,这时unexpected会默认调用terminate,terminate默认调用abort,程序被中止;

该情况极易发生:
编译器仅作局部检验,未检测到的是:

  • 一个函数调用另外一个函数 ,后者可能违反调用端函数的exception specifications
eg.

extern void f1();	 //可以抛出任何一种异常
 
void f2() throw(int);//只能抛出int类型异常
 
void f2() throw(int)
{
	...
	f1();	         //即使f1可能抛出非int异常也合法
	...
}
  • 会造成“当一个较高层次的调用者已经准备好要处理发生的exception时,unexpected函数却被调用”的现象。
class Session
{
public:
	~Session();
	...
private:
	static void logDestruction(Session* objAddr) throw();
};
 
 
Session::~Session()
{
	try{
		logDestruction(this);
	}
	catch(...)
	{
		
	}
}
//假设logDestruction调用的函数抛出异常,而logDestruction没拦住
//当非预期异常传到logDestruction,unexpected函数被调用,程序终止
//Session析构函数的catch块尚未执行程序就已经中止了
//所以将logDestruction的exception specifications去掉

事先预防unexpected exceptions的方法

  1. 避免让模板和exception specifications放在“需要类型自变量”的模板身上,最好是不要让模板和异常规格混用;
  2. 如果A函数内调用了B函数,而B函数无exception specifications,那么A函数本身也不要设定exception specifications(极易忽略的一种情况:允许用户注册回调函数的时候);
  3. 处理“系统”可能抛出的exception (最常见的就是bad_alloc,当内存分配失败的时候它被operator new和operator new[ ]抛出)。

直接处理unexpected exceptions的方法

  1. C++允许以不同类型的异常替换非预期的异常;
  2. 把非预期的异常转换成已知类型方法来替换unexpected,重新抛出当前异常,所有异常将被替换成bad_exception,这个异常替代原来的异常继续传递。
1.

class UnexpectedException{};	//所有的非预期异常都被它取代
 
void covertUnexpected()			//如果一个非预期异常抛出,便调用此函数
{
	throw UnexpectedException();
}

//并以covertUnexpected取代默认的unexpected函数
set_unexpected(covertUnexpected);

2.

void covertUnexpected()	//如果非预期异常被抛出,此函数便调用,它只是重新抛出当前异常
{
	throw;
}
 
set_unexpected(covertUnexpected);	//安装covertUnexpected,作为unexpected函数的替代

//任何非预期异常都被bad_exception取代,该异常取代原来的异常继续传递下去

总结

exception specifications是一把双刃剑,清晰说明了函数希望抛出怎样的异常,但是一旦违反就面临程序必须立刻中止的危险。编译器仅对exception specifications做局部的检验,很容易在不经意间违反,而且exception specifications还会妨碍更高层的异常处理函数处理未预期的异常,就算较高层已经知道怎么做了还是可能被提前中止,所以,在将exception specifications加入函数之前,需要再三审度它的行为效果及后果。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值