【问题标题】:Exception handling in terminate异常处理终止
【发布时间】:2017-08-13 17:08:27
【问题描述】:

我有以下终止处理程序:

void on_terminate() 
{
    std::exception_ptr eptr = std::current_exception();
    if (eptr)
    {
        try
        {
            std::rethrow_exception(eptr);
        }
        catch (const std::exception& e) 
        {
            DBG_FAIL(e.what());        
        }
        catch (...) 
        {
            DBG_FAIL("Unknown exception.");  
        }
    }
    else
    {
        DBG_FAIL("Terminate was called.");
    }    
}

我已经使用这个处理程序有一段时间了,我坚信它有效。但最近似乎当异常被抛出时,我仍然会在"Terminate was called." 结束。 (我仍然得到一个有用的调用堆栈。)

我在 VS2015 Up3 上遇到了这个问题,还没有时间检查其他编译器和平台。 (Cygwin 上的 GCC 还没有实现 exception_ptr。)我做错了什么吗?

给定以下代码:

int main(int argc, char* argv[]) 
{
    std::set_terminate(on_terminate);

    throw std::runtime_error("#yolo");
}

您可以测试该问题。

为了完整起见,您可以在这里找到我的dbg.h

【问题讨论】:

  • 不,因为 eptr 为空。裁判的问题是关于没有主动例外的重新抛出。这个问题更具体地说是关于 std::current_exception() 从终止处理程序返回 null 。 (但感谢您的努力。)

标签: c++ visual-studio-2015 exception-handling terminate


【解决方案1】:

不确定标准对此有何规定,但它也不适用于 VS2017。您可以通过以下方式获得所需的行为:

int main(int argc, char* argv[]) try
{
    std::set_terminate(on_terminate);

    throw std::runtime_error("#yolo");
}
catch (...) {
    std::get_terminate()();
}

这将从一个 catch 中调用您的终止方法,然后您的 on_terminate 中的 std::current_exception() 将起作用。

【讨论】:

  • 除了,我松开了调用堆栈。尽管调用堆栈中大约有 8 行垃圾,但到目前为止,我见过的所有编译器实现 MSC、GCC、Clang,都有整个调用堆栈直到引发异常。对我来说,这些信息比异常信息更有价值。
  • 是的,没错。那时我什么都没有。这个标准似乎不是很精确。它指出std::current_exception 返回当前正在处理的异常,并且在未找到处理程序时调用std::terminate,但我没有看到任何说明在调用std::terminate 时仍在处理异常。跨度>
  • 是的,我担心是这样。这是非常不幸的,因为那是一段很好的代码。它得到了调用堆栈和异常消息。因为我只让“这不可能发生”的情况进入 main,所以调用堆栈优先于消息。我会将这个答案标记为已接受。
  • 对于它的价值,似乎 gcc 和 Clang 都以正确的方式做这件事,并且从 C++11 标准的第 15.3.7 节中指出,当 @987654327 时隐式处理程序被认为是活动的@ 或 std::unexpected 被调用。好像VS出错了,我确实在msconnect上发现了一个bug,但是作为重复关闭了,我找不到重复的了。
  • 感谢您的澄清。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-19
  • 2015-12-09
相关资源
最近更新 更多