2011-09-19 59 views
2

我在一个大的项目,该模块主要包括了大量的代码像读码:“捕获”后关于C++的尝试-catch

try 
{ 
} 
catch(...) 
{ 
} 

从字面上看,括号,有“...”,在它。不像“异常e”。

这让我有点担心。 这种做法是好还是安全? 谢谢。

+0

我想像这是各种各样的通配符?其他人可以证实吗? – MGZero

+0

@MGZero,是的,它是一个通配符,它​​捕捉*一切*。 –

+0

复制[C++ try catch practices](http://stackoverflow.com/questions/2967062/c-try-catch-practices) –

回答

11

不,这是一个可怕的做法。

如果你catch(...),你不知道你发现了什么。它捕获所有C++异常(并且在某些平台上使用某些设置,它也捕获其他异常,例如Visual C++中的结构化异常)。

如果你不知道抛出了什么异常,你不知道系统的状态是什么:你怎么知道程序是否继续运行是安全的?

退出catch(...)块的唯一两种方法是终止程序或重新抛出异常(使用throw;)。如果在抛出异常但不能依赖析构函数的情况下需要执行一些清理操作,后者有时很有用。

+3

如果你需要做一些清理工作,并使用'throw;完成后重新抛出。当然,使用RAII类会更好。 – bdonlan

+0

@bdonlan:你说的没错,我想在你自己编写一个RAII容器的时候,在某些情况下使用catch(...)会很有用(我不记得曾经做过这,但我想这是可能的)。 –

+0

堆栈展开期间从析构函数抛出的异常终止程序;在RAII容器中,当析构函数中发生异常时显式中止程序以确保即使您不__正在执行堆栈展开 – bdonlan

1

它捕获所有异常。看到这个代码:

try { 
    throw CSomeOtherException(); 
} 
catch(...) { // Handle all exceptions 
    // Respond (perhaps only partially) to exception 
    throw;  // Pass exception to some other handler 
} 

MSDN

你并不需要声明这个参数;在很多情况下,它可能足以通知处理程序已发生特定类型的例外 。但是,如果您在 异常声明中未声明异常对象,则您将无法访问catch处理子句中的 中的该对象。

没有操作数的throw-expression会重新抛出当前正在处理的异常 。这样的表达式应该只出现在捕获处理程序中的处理程序或函数中。重新抛出的异常对象是原始异常对象(不是 副本)。例如:

希望这有助于!

这种做法是安全的,只有当你有正确的处理程序写入例外。避免它在我看来更好。

3

catch(...)捕获全部例外。

通常情况下,你不想这样做。你不知道你刚刚发现了什么,如果你离开catch块,你只是默默地忽略了某种错误。这可能会导致以后发生非常糟糕的事情。由于您不知道发生了什么错误,因此您无法从中恢复,因此唯一合理的做法是允许异常继续(重新抛出异常)或中止程序的执行(请致电abort()或致电abort()exit())。

但是,如果你有一些清理工作需要执行,也可能是合理捕获所有异常,进行清理,然后再次引发例外:

try { 
    // ... 
} catch (...) { 
    abortTransaction(); 
    throw; 
} 

这就是说,它通常是最好使用所谓的RAII classes自动执行此清理:

DBTransaction txn = db.StartTransaction(); 

// do stuff that may throw; if it throws, txn will be destroyed, 
// and its destructor can abort the transaction 
// As such, an explicit try { } catch(...) { } isn't needed