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

时间:2008-09-11 05:41:16

标签: c++ exception-handling try-catch

在C ++中,我试图在一个catch中捕获所有类型的异常(比如C#中的catch(Exception))。怎么做?更重要的是,如何才能抓住被零除的例外?

9 个答案:

答案 0 :(得分:23)

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

重要注意事项:

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

答案 1 :(得分:14)

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

这样做的原因是一些编译器(Visual C ++ 6命名最常见)也会将分段错误和其他非常糟糕的条件等错误转换为您可以使用catch(...)高兴地处理的异常。这非常糟糕,因为你再也看不到崩溃了。

从技术上讲,是的,你也可以将零除(你必须为“StackOverflow”),但你真的应该避免首先进行这样的划分。

相反,请执行以下操作:

  • 如果您确实知道会发生什么样的异常,请抓住这些类型,而不是
  • 如果您需要自己抛出异常,并且需要捕获所有将要抛出的异常,请将这些异常派生自std :: exception(如Adam Pierce建议的那样)并抓住它。

答案 2 :(得分:5)

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

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

_set_se_translator(myTranslator);

注意,代码会告诉您错误是什么。您还需要使用/ EHa选项进行编译(C / C ++ - &gt; Code Generatrion - &gt;启用C / C ++例外=是SEH例外)。

如果没有意义,请查看[_set_se_translator]的文档(http://msdn.microsoft.com/en-us/library/5z4bw5h5(VS.80).aspx)

答案 3 :(得分:4)

如果捕获所有异常 - 包括操作系统异常 - 真的是你需要的,你需要看看你的编译器和操作系统。例如,在Windows上,您可能使用“__try”关键字或编译器开关来“尝试/捕获”捕获SEH异常,或两者兼而有之。

答案 4 :(得分:3)

使所有自定义异常类继承自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!";
    }
};

答案 5 :(得分:1)

在C ++中,标准没有定义除零异常,并且实现往往不会抛出它们。

答案 6 :(得分:1)

当然,您可以使用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());
}

如果不使用boost,请使用析构函数创建自己的类。

答案 7 :(得分:0)

如果我没记错的话(自从我看过C ++已经有一段时间了),我认为以下应该可以做到这一点

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

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

答案 8 :(得分:0)

您可以使用catch(...)捕获所有内容,但随后您没有得到一个对象,即可对其进行完全检查,重新抛出,记录或执行任何操作。因此,您可以将try块“加倍”,然后重新放入一个可以处理单个类型的外部捕获器中。如果您为自定义异常类型定义构造函数,该异常类型可以从您希望组合在一起的所有种类中构建自身,则此方法非常理想。然后,您可以从catch(...)抛出一个默认构造的,其中可能包含诸如UNKNOWN之类的消息或代码,或者您想跟踪这些东西。

示例:

try
{ 
    try
    {       
        // do something that can produce various exception types
    }
    catch( const CustomExceptionA &e ){ throw e; } \
    catch( const CustomExceptionB &e ){ throw CustomExceptionA( e ); } \
    catch( const std::exception &e )  { throw CustomExceptionA( e ); } \
    catch( ... )                      { throw CustomExceptionA(); } \
} 
catch( const CustomExceptionA &e ) 
{
    // Handle any exception as CustomExceptionA
}