覆盖默认的未处理异常行为

时间:2015-10-01 14:46:43

标签: c++ c++11 exception-handling g++ visual-studio-2015

我有这段代码:

#include <iostream>
#include <exception>

class TestException : public std::exception
{
public:
    char const* what() const throw() override { return msg_.c_str(); }

protected:
    std::string & message() throw() { return msg_; }

private:
    std::string msg_;
};

void ThrowIt()
{
    throw TestException();
}

int main()
{
    ThrowIt();
}

在使用Visual Studio编译的Windows上的Release或Debug中内置运行时导致程序终止,在Linux机器上使用GCC编译时也是如此,结果是:

  

在抛出'TestException'实例后终止调用   what():Aborted

一旦捕获到未处理的异常,两者都会终止程序。此行为是严格针对系统的还是由标准指定的?是否存在跨平台方式,我可以将catch未处理的每个异常重新路由到处理程序而不是仅仅终止程序?

3 个答案:

答案 0 :(得分:0)

15.5.1 的C ++ 11标准声明:

  

[...]当异常处理机制找不到抛出异常[...] std::terminate()的处理程序时。在没有找到匹配处理程序的情况下,   它是实现定义的,无论在调用std::terminate()之前是否展开堆栈。

因此终止是标准行为,但是否可以从这种情况中恢复是实现定义的。在任何情况下都不会重新路由异常对象。

您还可以使用typedef void (*terminate_handler)();更改由std::terminate()调用的处理函数(terminate_handler set_terminate(terminate_handler f) noexcept;),并使用terminate_handler get_terminate() noexcept;进行查看。

答案 1 :(得分:0)

在您的代码中,您有一个未捕获的异常,因为您的异常没有匹配的句柄。这种行为包含在[except.terminate]

  

在某些情况下,必须放弃异常处理以获得不那么微妙的错误处理技术。 [注意:这些情况是:
  [...]
   - 当异常处理机制找不到抛出异常(15.3)的处理程序时,或   [...]

然后我们

  

在这种情况下,调用std :: terminate()(18.8.3)。在没有找到匹配处理程序的情况下,   它是实现定义的,无论是否在调用std :: terminate()之前展开堆栈。

如果你想拥有&#34;顶级&#34; catch将处理程序中的所有异常,如果未捕获,则可以将main()中的代码包装在try...catch块中。未捕获的任何异常将按[except.handle]

向上移动
  

如果在try块的处理程序中找不到匹配项,则在a中继续搜索匹配处理程序   动态地围绕同一个线程的try块。

您还可以使用std::set_terminate

更改std::terminate_handler

答案 2 :(得分:0)

我不确定什么标准保证,但在实践中使用 GCC、clang 和 MSVC,您可以在终止处理程序中使用 std::current_exception() 来处理异常。像这样:

#include <stdexcept>
#include <iostream>

void f()
{
    try
    {
        std::rethrow_exception(std::current_exception());
    }
    catch(const std::exception &e)
    {
        
        std::clog << "exception: " << e.what() << std::endl;
    }
}

int main()
{
    std::set_terminate(f);
    throw std::runtime_error("oh no");
    return 0;
}