如何在一个catch块中捕获所有类型的异常?

问题描述:

在C++中,我试图捕获所有类型的异常(如C#中的catch(Exception))。它是如何完成的?更重要的是,如何捕获零除异常?如何在一个catch块中捕获所有类型的异常?

catch (...) 
{ 
    // Handle exceptions not covered. 
} 

重要考虑:

  • 更好的方法是捕获特定类型的异常,你实际上可以从相对于所有可能的异常恢复。 (...)还会捕获某些严重的系统级异常(取决于编译器),您无法从中可靠恢复。以这种方式捕捉它们,然后吞食它们并继续进行,可能会在程序中导致更严重的问题。
  • 根据您的上下文,使用catch(...)可以接受,但重新抛出异常。在这种情况下,您记录所有有用的本地状态信息,然后重新抛出异常以允许它传播。但是,如果您选择此路线,则应该阅读RAII pattern
+0

不能让它赶上MySQL的错误(重复键)... – 2012-09-26 19:16:07

使所有自定义异常类从std :: exception继承,然后您可以简单地捕获std :: exception。下面是一些示例代码:

class WidgetError 
    : public std::exception 
{ 
public: 
    WidgetError() 
    { } 

    virtual ~WidgetError() throw() 
    { } 

    virtual const char *what() const throw() 
    { 
     return "You got you a widget error!"; 
    } 
}; 
+0

这是很好的做法,以减少catch块采空区(因为what()返回char字符串,而不是wchar_t字符串) – seand 2010-12-03 01:00:17

如果我没有记错(它已经有一段时间,因为我已经看了C++),我认为下面应该做的伎俩

try 
{ 
// some code 
} 
catch(...) 
{ 
// catch anything 
} 

和快速谷歌(http://www.oreillynet.com/pub/a/network/2003/05/05/cpluspocketref.html)似乎证明我是正确的。

+0

在Windows中可能不安全,并且可能它会阻止访问违规和其他真正的错误发生 – seand 2010-12-03 03:58:38

在C++中,标准没有定义除数为零的例外,并且实现往往不会抛出它们。

不要想要使用catch(...)(即捕获省略号),除非你真的,绝对的,最可证明的需要它。

原因是某些编译器(Visual C++ 6最常见的名称)也会将错误(如段错误和其他非常糟糕的情况)转换为可以使用catch(...)很乐意处理的异常。这很糟糕,因为你再也看不到崩溃了。

从技术上讲,是的,你也可以通过零来捕捉分割(你将不得不为“*”),但你应该首先避免做出这样的分割。

相反,做到以下几点:

  • 如果你真的知道会发生什么样的异常(S)的,赶上这些类型并没有更多的,和
  • 如果你需要给自己抛出异常,并需要捕获所有将抛出的异常,并使这些异常来自std :: exception(正如亚当皮尔斯所建议的)并捕获它。

如果捕获所有异常(包括操作系统异常)实际上是您需要的,那么您需要查看一下编译器和操作系统。例如,在Windows上,您可能会使用“__try”关键字或编译器切换来使“try/catch”捕获SEH异常,或者两者都有。

+0

ebel gil:谢谢你,你的回答非常有帮助! – gil 2008-09-11 09:43:35

当然,您可以使用catch (...) { /* code here */ },但它确实取决于您想要做什么。在C++中,你有确定性的析构函数(没有任何最终化垃圾),所以如果你想要扫描,正确的做法是使用RAII。

例如。而不是:

void myfunc() 
{ 
    void* h = get_handle_that_must_be_released(); 
    try { random_func(h); } 
    catch (...) { release_object(h); throw; } 
    release_object(h); 

} 

做这样的事情:

#include<boost/shared_ptr.hpp> 

void my_func() 
{ 
    boost::shared_ptr<void> h(get_handle_that_must_be_released(), release_object); 
    random_func(h.get()); 
} 

与析构函数创建自己的类,如果你不使用升压。

如果您在Windows上并且需要处理除以零和访问冲突等错误,则可以使用结构化的异常转换程序。然后您翻译的里面,你可以抛出一个C++异常:

void myTranslator(unsigned code, EXCEPTION_POINTERS*) 
{ 
    throw std::exception(<appropriate string here>); 
} 

_set_se_translator(myTranslator); 

注意,该代码会告诉你是什么错误。你也需要使用/ EHa选项进行编译(C/C++ - >代码生成 - >启用C/C++异常=有SEH异常)。

如果这样做没有意义结账的文档为[_set_se_translator(http://msdn.microsoft.com/en-us/library/5z4bw5h5(VS.80).aspx)