【问题标题】:Can I use std::current_exception during stack unwinding?我可以在堆栈展开期间使用 std::current_exception 吗?
【发布时间】:2015-02-01 20:28:47
【问题描述】:

是否可以在堆栈展开期间销毁的对象的析构函数中使用 std::current_exception?

Documentation on cppreference 说:

如果在异常处理期间(通常在 catch 子句中)调用,则捕获当前异常对象 (...)

但我不清楚堆栈展开是否是异常处理的一部分。

在 stackoverflow 上的一些 highest-ranked answer 中,作者认为这是可能的。

我对我的编译器 (g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2) 做了一些测试,似乎在这种情况下 std::current_exception 返回空指针。

#include <exception>
#include <stdexcept>
#include <iostream>


struct A
{
    ~A()
    {
        std::clog << "in destructor"<<std::endl;
        std::clog << "uncaught_exception: " << std::uncaught_exception() << std::endl;
        std::clog << "current_exception: " << (bool)std::current_exception() << std::endl;
    }
};

int main(int argc, char **)
{
    try
    {
        A aa;
        std::clog << "before throw"<<std::endl;
        if(argc>1)
            throw std::runtime_error("oh no");
    }
    catch(...)
    {
        std::clog << "in catch block"<<std::endl;
        std::clog << "uncaught_exception: " << std::uncaught_exception() << std::endl;
        std::clog << "current_exception: " << (bool)std::current_exception() << std::endl;
    }

    return 0;
}

输出是:

before throw
in destructor
uncaught_exception: 1
current_exception: 0
in catch block
uncaught_exception: 0
current_exception: 1

有人知道标准是怎么说的吗?

【问题讨论】:

    标签: c++ c++11 exception-handling


    【解决方案1】:

    C++ 标准在第 18.8.5 节 [传播] 中定义了 current_exception()

    (强调我的)

    exception_ptr current_exception() noexcept;

    返回:引用当前处理的 exception_ptr 对象 异常 (15.3) 或当前处理的异常的副本,或 如果没有处理异常,则为 null exception_ptr 对象。这 被引用的对象至少只要有一个 引用它的 exception_ptr 对象。

    以及 § 15.3 [except.handle],注释 7 和 8:

    1. 当初始化完成时,处理程序被视为活动 catch 子句的参数(如果有)。 [ 注意:堆栈将有 那时已经解散了。 ——尾注]

    2. 最近激活的 处理程序仍处于异常状态 active 被称为当前处理的异常

    current_exception()返回的异常定义为“当前处理的异常”,是最近活动的handler的异常,只有在堆栈展开完成时,handler才处于活动状态。


    正如您的测试所示,在堆栈展开期间没有“活动处理程序”,因此也没有“当前处理的异常”:在这种情况下,current_exception() 将返回 null @ 987654328@.

    【讨论】:

    • "在堆栈展开期间没有"活动异常"",除非异常正在被捕获处理或从析构函数调用。
    • @Cheersandhth.-Alf 没错,我更正了措辞,请阅读没有“活动处理程序”(标准措辞)
    • 嗯,很难做到正确,以至于 Some™ 怀疑这可能是 std::uncaught_exception 无法用于任何目的的原因。 ;-)
    • 这似乎是正确的。我也很惊讶;我可以看到在 d'tors 的异常情况下达到峰值的良好用途;尤其是基于 RAII 的日志记录。
    猜你喜欢
    • 2014-04-17
    • 1970-01-01
    • 2017-08-16
    • 2015-08-12
    • 2011-12-13
    • 2016-09-15
    • 2020-12-26
    • 2015-08-15
    • 2012-10-29
    相关资源
    最近更新 更多