返回信息流How to handle constructor that fails and how to handle destructor that fails ?
这是一条镜像帖。来源:北邮人论坛 / cpp / #31144同步于 2009/11/11
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
How to handle constructor that fails
yihang
2009/11/11镜像同步8 回复
订阅后,新回复会通过你的通知中心匿名送达。
8 条回复
【 在 yihang 的大作中提到: 】
: How to handle constructor that fails and how to handle destructor that fails ?
这一点symbian的c++代码考虑得很周全,感兴趣的话不妨看下
【 在 jokerlee 的大作中提到: 】
: 一般都是 bad allocation吧 catch到以后abort?
直接abort不好吧,有点不负责任的感觉
对于析构该如何处理呢?
to jmpesp, symbian不了解,能简述一下大致思路么?
2-phase construction
new (ELeave)
cleanup stack
TRAP and TRAPD
:-)
【 在 jmpesp 的大作中提到: 】
: 这一点symbian的c++代码考虑得很周全,感兴趣的话不妨看下
【 在 jmpesp 的大作中提到: 】
: 这一点symbian的c++代码考虑得很周全,感兴趣的话不妨看下
ls说的很清除了。具体的就是,二阶段构造,就是在可能出现异常的代码不在构造函数内部写上,而是独立出来形成一个函数,然后构造函数被自动调用后我们再主动对那个独立出来的函数进行调用。说白了,就是不在构造函数中存放可能异常退出的代码。
In general one could use set_new_handler() to deal with construct failures. Well, set_new_handler() gives you the last chance to save your day, however, it has better to used to tackle with those unclosed file handlers, to shut down any holding resources(devices, databases...), or to flush the input and output streams. But again, you will have to face the same problem.
The question should be refined to what techniques should be exploited or which approach should be taken to avoid failure. IMHO, there exist at least 3 steps to relieve the situation:
1. Never write too complicated code in constructor. The only responsibility of the constructor is to create an object from nowhere. So less code, less error.
2. Never write code that will throw exceptions in your constructor except new method. New method is related to object creation so much that we cannot pass over it. But we can try our best not to introduce other sources of exceptions. As far as no exception code written in constructor, and pushing all complex routines down to an outside function which we could actively invoke afterwards, we can avoid large amount of constructor error. (Raiden's words)
3. The only problem remaining here is there is still a little chance, no matter how slim, that the new method would throw exceptions. We can solve this by using the new method atomically, i.e., always use wrappers instead of raw pointers. See the following example.
class A {
public:
A() {
some_pointer * pa = ...new...
// if here throws an exception, the new method above would cause leakage...
// because the constructor does not finish...
// even you write "delete pa" in the destructor, there is still no chance to run it.
some_other_pointer * pb = ...new...
}
};
But we can introduce a object to hold the raw pointer so that the object's destructor can take care of the raw pointer. This object is called auto_ptr, an overlooked built-in infrastructure.
class A {
public:
A() {
auto_ptr<some_type> pa(new type);
// if we throw an exception here, the destructor of class A cannot be run,
// but the destructor of the class auto_ptr will be run. NO LEAKAGE!
auto_ptr<some_other_type> pb(new other_type);
}
};
这些思想跟symbian的处理方法其实都是类似的
【 在 ericyosho 的大作中提到: 】
: In general one could use set_new_handler() to deal with construct failures. Well, set_new_handler() gives you the last chance to save your day, however, it has better to used to tackle with those unclosed file handlers, to shut down any holding resources(devices, databases...), or to flush the input and output streams. But again, you will have to face the same problem.
: The question should be refined to what techniques should be exploited or which approach should be taken to avoid failure. IMHO, there exist at least 3 steps to relieve the situation:
: 1. Never write too complicated code in constructor. The only responsibility of the constructor is to create an object from nowhere. So less code, less error.
: ...................