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

时间:2020-03-05 18:51:14  来源:igfitidea点击:

在C ++中,我试图一次捕获所有类型的异常(例如C#中的catch(Exception))。怎么做?而且,如何捕获零除异常?

解决方案

回答

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

重要注意事项:

  • 更好的方法是捕获实际可以从中恢复的特定类型的异常,而不是所有可能的异常。
  • catch(...)还将捕获某些严重的系统级异常(因编译器而异),我们将无法从中可靠地恢复这些异常。以这种方式捕获它们,然后将其吞下并继续可能会在程序中引起进一步的严重问题。
  • 根据上下文,使用catch(...)是可以接受的,前提是该异常被重新抛出。在这种情况下,我们记录所有有用的本地状态信息,然后重新引发异常以使其向上传播。但是,如果选择此路线,则应阅读RAII模式。

回答

让我们所有的自定义异常类都继承自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!";
    }
};

回答

如果我没记错(自从看过C ++已经有一段时间了),我认为以下方法可以解决问题

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

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

回答

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

回答

我们不希望使用catch(...)(即用省略号进行catch),除非我们确实,确实,大多数可证明的人都需要它。

这样做的原因是某些编译器(最常见的是Visual C ++ 6)也将诸如段错误和其他真正糟糕的条件之类的错误转换为可以使用catch(...)轻松处理的异常。这非常糟糕,因为我们不再看到崩溃了。

从技术上讲,是的,我们还可以用零除(必须使用" StackOverflow"),但实际上我们应该首先避免进行此类除。

而是,请执行以下操作:

  • 如果我们实际上知道将要遇到的异常类型,则不要再捕获这些类型,并且
  • 如果我们需要自己抛出异常,并且需要捕获将要抛出的所有异常,请使这些异常派生自std :: exception(如Adam Pierce所建议)并捕获该异常。

回答

如果确实需要捕获包括OS异常在内的所有异常,则需要查看编译器和OS。例如,在Windows上,我们可能具有" __try"关键字或者编译器开关,以使" try / catch"捕获SEH异常,或者同时发生这两种情况。

回答

当然,我们可以使用catch(...){/ *代码* /},但这实际上取决于我们要执行的操作。在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,请使用析构函数创建自己的类。

回答

如果我们在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/zh-cn/library/5z4bw5h5(VS.80).aspx)