What is a good way in C++ to detect in a destructor that it is being run during unwind of the stack due to an exception being thrown as opposed to a normal exit of scope triggering the destructor? I'd like to know so that I can create a class that has some cleanup code that is always run on normal exit but skipped when an exception occurs.
std::uncaught_exception()
(defined in <exception>
) will tell you in your destructor if it was called because of an exception:
class A
{
public:
~A()
{
if (std::uncaught_exception()) {
// Called because of an exception
} else {
// No exception
}
}
};
std::uncaught_exceptions()
(plural) –
Portecochere Probably this article will help you. The article will show you the problems with std::uncaught_exception() and contains an advice how to deal with exceptions in destructors.
uncaught_exceptions
is not robust. –
Salford Don't do that unless you have a good reason. The stack unwinding is such a language feature that all automatic objects inside try
block will be enforced to deallocate, so that the resources inside them have a chance to release.
You want skip cleanup in dtor during stack unwinding, which bypasses the original intention of it. And you'll run the risk of leaking resources.
Example
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's a resource leakage.
}
//..
private:
DB m_db;
};
void main()
{
//..
try
{
// code that may throw
CDBConnection db;
//..
}
catch(const CDBException& exp)
{
// properly handle the exception
}
}
Here is one way I can think of, but it seems clumsy:
{
myCleanupClass unwindAction;
try {
// do some work which may throw exception.
} catch (...) {
unwindAction.disableDestructorWork();
throw;
}
}
© 2022 - 2024 — McMap. All rights reserved.
stack
logging. Something along the lines ofLog xxx("funcA - ", arg1, arg2, arg3);
, but instrumenting the functions is tedious. – Natalityinst.CleanupCode()
on normal exit than fiddle with the destructor. I think this is a case where trying to use RAII to solve error handling and normal program execution is just going to cause a headache. – Salford