Что такое хороший способ в С++ обнаруживать в деструкторе, что он выполняется во время разрыва стека из-за того, что исключение выбрано в отличие от обычного выхода из области действия, запускающей деструктор? Я хотел бы знать, что я могу создать класс с некоторым кодом очистки, который всегда запускается при нормальном выходе, но пропускается, когда возникает исключение.
Обнаружение при запуске деструктора из-за исключения исключения?
Ответ 1
std::uncaught_exception()
(определенный в <exception>
) сообщит вам в вашем деструкторе, если он был вызван из-за исключения:
class A
{
public:
~A()
{
if (std::uncaught_exception()) {
// Called because of an exception
} else {
// No exception
}
}
};
Ответ 2
Возможно эта статья поможет вам. В статье расскажут о проблемах с std:: uncaught_exception() и содержит рекомендации по устранению исключений в деструкторах.
Ответ 3
Не делай этого, если у тебя нет веской причины. Распаковка стека - это такая языковая функция, что все автоматические объекты внутри блока try
будут принудительно освобождены, чтобы ресурсы внутри них имели возможность освободить.
Вы хотите пропустить очистку в dtor во время разматывания стека, что обходит первоначальное намерение. И вы рискуете утечкой ресурсов.
Пример
class CDBConnection
{
public:
CDBConnection()
{
m_db.open();
}
~CDBConnection()
{
if (!std::uncaught_exception())
m_db.close();
// if this is called during a stack unwinding,
// your DB connection will not be closed for sure.
// That a resource leakage.
}
//..
private:
DB m_db;
};
void main()
{
//..
try
{
// code that may throw
CDBConnection db;
//..
}
catch(const CDBException& exp)
{
// properly handle the exception
}
}
Ответ 4
Вот один из способов, о котором я могу думать, но это кажется неуклюжим:
{
myCleanupClass unwindAction;
try {
// do some work which may throw exception.
} catch (...) {
unwindAction.disableDestructorWork();
throw;
}
}