我知道析构函数不应该抛出异常。
http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.13
我有以下代码:
~a()
{
cleanup();
}
// I do not expect exception being thrown in this function.
// If exception really happen, I know that it is something not recoverable.
void a::cleaup()
{
delete p;
}
在我的静态源代码分析中,它抱怨我将以这种方式调用清理函数:
~a()
{
try {
cleanup();
}
catch(...) {
// What to do? Print out some logging message?
}
}
// I do not expect exception being thrown in this function.
// If exception really happen, I know that it is something not recoverable.
void a::cleaup()
{
delete p;
}
我不确定这是一个好习惯,在析构函数中放置try ... catch块,只要它调用函数。作为:
(1)如果清理功能能够抛出异常,我知道发生了一些不好的事情。我更喜欢fail-fast。也就是说,让整个系统崩溃,让程序员调试它。
(2)进入和退出try ... catch块时发生开销。
(3)代码看起来很麻烦,在类的析构函数中有很多try ... catch块。
我可能会错过其他一些观点,为什么要尝试......抓住障碍应该到位。
感谢。
答案 0 :(得分:3)
由于delete
不会抛出,cleanup
也不会抛出,因此无需将调用放入try-catch。
由于您的静态分析工具可能很难搞清楚,或许您可以通过将cleanup
声明为无投掷来帮助它(这只是猜测)。
void cleanup() throw();
答案 1 :(得分:2)
也许你可以更精确地了解你的清理功能。如果仅在非常罕见的情况下,cleanup()函数是否故意抛出异常?那么你肯定应该在你的析构函数中处理这个案例,因为即使很少见,抛出异常也是cleanup()的预期行为。
至少,您的异常处理代码可能会使您的程序处于定义良好的状态,从而可以优雅地结束您的程序。
或者你的意思是清理()可能会抛出,例如一个OutOfMemoryException或另一个你从未在其他地方处理过的运行时异常?然后我也会在析构函数中省略异常处理。在这种特殊情况下,您的应用程序可能无法运行其错误处理代码。您应该尽一切可能确保即使报告或正确记录此类异常也是如此。
编辑:
现在你已经展示了cleanup
的实现,Neil已经回答了你的问题。 delete p
不能抛出,因此a::cleanup
只要p
的析构函数不抛出就不会抛出。{/ p>
答案 2 :(得分:1)
当然,这个问题确实存在于p的析构函数中。在清理()时,你说
delete p;
delete本身不能抛出,因此异常必须来自p的析构函数。在析构函数中,您需要担心使用try块,而不是使用try块。
答案 3 :(得分:1)
从根本上说,当已经处理异常时抛出异常是不安全的。
如果在堆栈展开时调用析构函数,并抛出另一个异常,那么你的线程可以在某些系统(例如Symbian)上立即终止;您的代码计划捕获异常将不会停止该终止 - 您的代码甚至不会被调用。如果您的exception escapes the destructor。
,您的帖子肯定会被终止因此,析构函数中的try {} catch(...) {}
不是可移植的,并且当然很棘手。
声音建议永远不会调用可能会在 cleanup 代码中抛出异常的代码,例如析构函数和可能从析构函数调用的任何函数,例如“cleanup()
”, close()
'或'release_something()
'。
原始海报还会查询try-catch的性能。在采用C ++异常的早期,异常处理代码相当昂贵;目前,您的编译器几乎肯定使用零成本异常,这意味着未抛出的异常不会给代码带来运行时性能损失(但当然会略微增加程序的二进制大小)。
答案 4 :(得分:1)
由于内存分配或删除,抛出错误通常没有任何意义。无论是否有效,您可以花费大量的工作来处理愚蠢的错误,而不会获得任何好处。
您可能希望在特定情况下执行此操作,但在实践中也没有做太多,如果有问题,您通常需要使用调试器或更完整的工具。
答案 5 :(得分:0)
我从不使用此功能,但异常安全纯粹主义者会说你的cleanup()
功能可能会在你没有预料到的情况下抛出。所以这种模式是一种额外安全的技术。
但是,cleanup
函数不应该放在第一位。所以我会在cleanup()
中放置任何异常处理,而不是在析构函数本身。