Подтвердить что ты не робот

Можно ли использовать std:: current_exception во время разматывания стека?

Можно ли использовать 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;
}

Вывод:

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

Кто-нибудь знает, что говорит стандарт?

4b9b3361

Ответ 1

Стандарт С++ определяет current_exception() в разделе § 18.8.5 [распространение]:

(акцент мой)

exception_ptr current_exception() noexcept;

Возвращает: объект exception_ptr, который относится к обрабатываемой в настоящее время исключение (15.3) или копию обработанного в настоящее время исключения или null exception_ptr object, если исключение не обрабатывается. объект, на который ссылается, остается действительным по меньшей мере до тех пор, пока существует exception_ptr, который ссылается на него.

И § 15.3 [except.handle], примечания 7 и 8:

  1. Обработчик считается активным, когда инициализация завершена для параметр (если таковой имеется) положения catch. [Примечание: Стек будет иметь был раскручен в этот момент. - конец примечания]

  2. Исключение с последним активированным обработчиком , который все еще active называется обработанным в настоящее время исключением.

Исключение, возвращаемое current_exception(), определяется как "обработанное в настоящее время исключение", которое является исключением самого последнего активного обработчика и активен обработчик только при завершении стирания стека.


Как показали ваши тесты, во время разворачивания стека нет "активного обработчика", поэтому нет "обработанного в настоящее время исключения": в этом случае current_exception() вернет null exception_ptr.