Можно ли использовать 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
Кто-нибудь знает, что говорит стандарт?
Ответы
Ответ 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:
-
Обработчик считается активным, когда инициализация завершена для параметр (если таковой имеется) положения catch. [Примечание: Стек будет иметь был раскручен в этот момент. - конец примечания]
-
Исключение с последним активированным обработчиком , который все еще active называется обработанным в настоящее время исключением.
Исключение, возвращаемое current_exception()
, определяется как "обработанное в настоящее время исключение", которое является исключением самого последнего активного обработчика и активен обработчик только при завершении стирания стека.
Как показали ваши тесты, во время разворачивания стека нет "активного обработчика", поэтому нет "обработанного в настоящее время исключения": в этом случае current_exception()
вернет null exception_ptr
.