在堆栈展开期间我可以使用std :: current_exception吗?

pep*_*er0 28 c++ exception-handling c++11

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

有关cppreference的文档说:

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

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

在stackoverflow的一些排名最高的答案中,作者认为这是可能的.

我对我的编译器进行了一些测试(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;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

before throw
in destructor
uncaught_exception: 1
current_exception: 0
in catch block
uncaught_exception: 0
current_exception: 1
Run Code Online (Sandbox Code Playgroud)

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

qua*_*dev 21

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

(强调我的)

exception_ptr current_exception() noexcept;

返回:一个exception_ptr对象,它引用当前处理的异常(15.3)或当前处理的异常的副本,如果没有处理异常,则返回null exception_ptr对象.只要存在引用它的exception_ptr对象,引用的对象应至少保持有效.

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

  1. 当catch子句的参数(如果有)的初始化完成时,处理程序被认为是活动的.[注意:此时堆栈将被解开. - 结束说明]

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

返回的异常current_exception()被定义为"当前处理的异常",这是最新的活动处理程序的例外,并且只有在堆栈展开完成时处理程序才处于活动状态.


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