C++17中uncaught_exceptions()能否返回大于1的数值?
关于C++17中
uncaught_exceptions()返回值大于1的场景疑问 C++17引入了int uncaught_exceptions() noexcept;来替代bool uncaught_exception() noexcept;,这引发了一个疑问:是否可能同时存在多个未捕获的异常?
根据相关文档描述:
返回值
2. 当前线程中未捕获异常对象的数量。
我尝试设想返回值大于1的场景,一开始想到的思路是:在同一个try块内,于局部变量的destructor中执行throw操作。但这并不可行:
- 首先,这违反了析构函数必须为
noexcept的规则; - 其次,即便通过
noexcept(false)修正,程序也只会调用terminate,而非进入catch块。
另外,在catch块内抛出异常属于常规操作,但一旦进入catch块,uncaught_exceptions()的值就会递减至0,所以这种情况也无法让返回值大于1。
那么,是否存在能让uncaught_exceptions()返回大于1数值的场景?
答案是存在,典型场景是在异常栈展开(stack unwinding)的过程中,调用的某个函数(比如另一个对象的析构函数)再次抛出异常,且这个新抛出的异常被处理前的短暂阶段,uncaught_exceptions()的返回值会大于1。
举个具体的代码例子:
#include <iostream> #include <exception> struct Foo { ~Foo() noexcept(false) { throw std::runtime_error("Destructor exception"); } }; struct Bar { ~Bar() { std::cout << "uncaught_exceptions() during Bar destructor: " << std::uncaught_exceptions() << '\n'; Foo f; // 析构Foo时抛出新异常 } }; int main() { try { Bar b; throw std::logic_error("Main exception"); } catch (...) { std::cout << "uncaught_exceptions() in catch block: " << std::uncaught_exceptions() << '\n'; } }
这段代码的执行流程细节:
main函数抛出logic_error,触发栈展开,开始销毁Bar对象;Bar的析构函数执行时,uncaught_exceptions()返回1(此时第一个异常还未被捕获);- 创建
Foo对象后销毁,Foo的析构函数抛出runtime_error,此时栈展开过程中存在两个未被处理的异常,uncaught_exceptions()的值变为2; - 最终外层
catch(...)捕获所有异常后,uncaught_exceptions()回到0。
需要注意的是,在C++11及以后,若在栈展开过程中(已有未捕获异常时)再次抛出异常且无对应处理,程序会调用std::terminate,但在抛出新异常到terminate被调用前的这个阶段,uncaught_exceptions()的返回值确实大于1。
内容的提问来源于stack exchange,提问作者unegare
相关产品推荐
相关产品推荐

