Re: What risk of undefined behavior if destructor must throw?
Terry G wrote:
In my example, ReleaseMutex has failed. It shouldn't have, but it did.
Microsoft doesn't say why ReleaseMutex might fail, until it actually does.
Then you can call GetLastError to find out why, after the fact.
The point here is not that Microsoft is evil, its just that destructors have
to "trust" that other code will succeed. But it might not.
You can call GetLastError and log the error. You might even want to
assert, because an assert is not really an exception and it means
there's a bug in your code somewhere. ReleaseMutex probably fails
because your thread does not own the mutex.
So, in my destructor I have three choices: terminate right now, ignore the
error, or throw. Terminate seems drastic in this example. Ignoring the error could cause
the program to hang, become unstable, or produce incorrect results, a fate worse
than death in an embedded system.
Ignoring the error may be fine. That is, if when you call ReleaseMutex
that simply means you don't want the thread to have the mutex. You
don't care if your thread had it originally or not, as long as it
doesn't have it now.
If you are expecting that your thread does have the mutex at the time
you make the call then it is a failed assertion.
Throwing seems like the best choice here.
No, throwing is the wrong action. Throwing an exception happens because
of runtime conditions. You might throw an exception if a wait times out
because you don't expect that to happen.
It seems to me to be the best choice most of the time. In fact, I'd really
like to throw something that forces the program to terminate, because
continuing to operate would be bad. So shutdown gracefully. But shutdown!
However, most of my collegues have read these books and routinely put
catch(...) in their code.
"Don't use catch(...)" seems like stronger advice than "don't let
destructors throw."
As a hard and fast rule I'd go for the 2nd one. Better to use
catch(...) than let a destructor throw. Better to catch first any
exceptions you might be able to handle. As all your exceptions should
hopefully derive from std::exception that shouldn't be a problem.
I note that you claim to be writing an embedded system and yet you are
using exceptions. That sounds rather unusual.
That way I could throw a Terminate() exception, not derived from anything,
which would fully unwind the stack, and then terminate.
You'll want to know first why the original exception was thrown though.
It may be a reason for which to terminate, it might not be. To me,
termination seems like a last resort. I don't know what type of
application you are writing, but for me there is often nothing worse
than have an app crash on me.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]