15

我刚刚注意到

http://en.cppreference.com/w/cpp/error/uncaught_exception

那个 C++17 将替换std::uncaught_exception(), 它返回一个bool, with std::uncaught_exceptions(), 它返回一个int.

对描述这一点的标准的补充如下:

http://isocpp.org/files/papers/n4259.pdf

它没有提供理由,但确实说

[注意:当 uncaught_exceptions() > 0 时,抛出异常会导致调用 std::terminate() (15.5.1)。– 结束注]

这是奇怪的模糊。

这种变化的原因是什么?在 C++17 或标准的某些未来版本中是否会出现多个活动异常?

4

3 回答 3

22

介绍这一点的论文是n4152,它具有基本原理(通常归结为“使 ScopeGuard 工作”)

去引用,

正如至少自 1998 年以来在 Guru of the Week #47 中所记录的那样,这意味着从析构函数中传递调用的代码本身可以在堆栈展开期间被调用,无法正确检测它本身是否实际上被作为展开的一部分调用。一旦你在展开任何异常,uncaught_exception一切看起来就像展开,即使有不止一个活动异常。

这使用了主要实现中已经存在的信息,其中 ScopeGuard 的当前实现采用依赖未记录的编译器功能的不可移植代码,以使 ScopeGuard 在今天“在实践中可移植”。此选项建议添加一个新函数来公开编译器中已经存在的信息,以便这些使用可以真正可移植

PS:这是一个如何使用编译器特定信息实现此功能的示例:https ://github.com/panaseleus/stack_unwinding/blob/master/boost/exception/uncaught_exception_count.hpp

对于一个使用它的简单示例,只需查看 boost.log 的“记录泵”(参见boost/log/detail/ format.hpp和boost/log/sources/record_ostream.hpp):它使BOOST_LOG(lg) << foo();记录成为可能在它创建的保护对象的析构函数中,如果foo不抛出,也就是说,如果调用析构函数时发生的异常数量不大于调用构造函数时的异常数量。

于 2015-01-02T11:43:55.773 回答
0

std::uncaught_exception() 仅检测堆栈是否正在展开。在 Herb Sutter 的一篇论文中,他指出这并不能可靠地表明存在活动异常。Herb 认为这“几乎”有用。我遇到过这种情况确实模棱两可,这就是导致我写这篇文章的原因。

std::uncaught_exceptions() is specified as returning the number of active exceptions, which is actually useful.

于 2016-02-19T17:25:42.523 回答
0

note that std::uncaught_exception() can still be useful for debug/loginfo. It can help determine where the exception originated. However I agree functionally, its quite useless.

于 2018-02-02T20:05:46.337 回答