Как я могу определить, активно ли исключение во время деструктора?
В C++, как я могу обнаружить в теле моего деструктора, разворачивается ли стек из-за исключения? Могу ли я получить ссылку на активное исключение после обнаружения?
Я спрашиваю, потому что я хотел бы добавить некоторый код отладки, который объясняет, почему может возникать определенная ситуация и происходит ли это из-за исключений или нет.
4 ответа
std::uncaught_exception
говорит вам, что стек разматывается из-за создаваемого исключения, о чем вы и просили.
Тем не менее, он не говорит вам, что вы, вероятно, хотите знать: находится ли объект, от деструктора которого вы его вызываете, в той части стека, которая разматывается, или в части стека, которая обычно уничтожается из-за Исключительно выход из области действия под другим деструктором, который является частью раскрутки:
struct A {
~A();
};
struct B {
~B();
}
int main() {
try {
A a;
throw 1;
} catch(...) {}
}
A::~A() {
std::uncaught_exception(); // true
B b;
}
B::~B() {
std::uncaught_exception(); // also true, but "b" isn't being "unwound",
// because ~A() returned, it didn't throw.
}
Вопреки словам DeadMG и Xeo, вы не можете получить ссылку на исключение, которое не было обнаружено. throw
без операнда сбрасывает "текущее обработанное исключение", то есть исключение, в обработчике которого вы находитесь или чей-обработчик вызвал вас. Это не отбрасывает неисследованное исключение.
А как насчет нового C++17 std::uncaught_exceptions()
? Я думаю, что вы можете создать код, который выглядит следующим образом:
class ExceptionSentinel
{
int prev_uncaught;
public:
ExceptionSentinel() : prev_uncaught(std::uncaught_exceptions()) {}
~ExceptionSentinel()
{
int cur_uncaught = std::uncaught_exceptions();
if (cur_uncaught > prev_uncaught)
{
// ... ExceptionSentinel is being destructed by an stack unwinding process
}
else
{
// ... Normal destruction of ExceptionSentinel
}
}
};
В этом случае, std::uncaught_exceptions()
отслеживает число необработанных исключений к моменту вызова кода. Больше информации можно найти на странице cppreference.
E сть std::uncaught_exception()
функция. Однако, единственная полезная вещь, которую вы можете сделать, чтобы попытаться получить доступ к объекту исключения, - это сбросить его и попытаться его поймать. Вы никогда не должны бросать исключения из любого деструктора, в общем.
В C++, как я могу обнаружить в теле моего деструктора, разворачивается ли стек из-за исключения?
Не.
Могу ли я получить ссылку на активное исключение после обнаружения?
Нет.