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

Can I use std::current_exception during stack unwinding?

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

Documentation on cppreference 说:

If called during exception handling (typically, in a catch clause), captures the current exception object (...)

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

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

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

#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++ 标准在第 18.8.5 节 [传播] 中定义 current_exception() :

(强调我的)

exception_ptr current_exception() noexcept;

Returns: An exception_ptr object that refers to the currently handled exception (15.3) or a copy of the currently handled exception, or a null exception_ptr object if no exception is being handled. The referenced object shall remain valid at least as long as there is an exception_ptr object that refers to it.

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

  1. A handler is considered active when initialization is complete for the parameter (if any) of the catch clause. [ Note: The stack will have been unwound at that point. — end note ]

  2. The exception with the most recently activated handler that is still active is called the currently handled exception.

current_exception()编辑的异常return定义为"currently handled exception",这是最近活动的处理程序的异常,只有当堆栈展开完成时处理程序才处于活动状态.


如您的测试所示,在 堆栈展开期间没有 "active handler" ,因此也没有 "currently handled exception":在这种情况下,current_exception() 将 return 为 null exception_ptr.