I am reading following text in applied C++ book.
Can exceptions be thrown from within our handler functions? The answer
is yes, an error can indeed be thrown. The problem is that this
exception must be in every exception specification that may be
tranversed until the exception is caught. If this is not done, the
application will call std::terminate(). For a large system, this
amounts to adding an exception specification to every function ,
unless you understand the dynamics of your application perfectly. It
is also important to cath all exceptions within your destructor;
otherwise, std::terminate() will be called as well in this case.
In above text I have following questions and need your help in understanding.
What does author mean by "exception must be in every expection specification that may be traversed" ?
My understanding is that destructor we cannot use exceptions. What does author mean to catch all exceptions within your destructor.
Request to clarify with simple examples
Thanks for your time and help.
Generally, exception specifications are a bad idea, because it produces a lot of refactoring and scale problems (The problems wich the autor talks about) when you modify the specifications. This is the case of java checked exceptions. C++ has no checked exceptions, but the problem with exception specifications are the same, if you want to write an uniform API.
In fact exception specifications are deprecated since C++11. C++11 uses noexcept specifier to ensure that a function not throws any exception. This allows certain compiler optimizations, and of course provides guaranties for the user of the function. If a function doesn't have the noexcept specifier, it can throw a exception or not.
Exceptions are, as it name says, exceptional. That is, using try...catch for flow-control is a bad programming technique. If your program is well designed, when a exception is thrown, means something go very very wrong. That is, a exceptional execution case. And normally that exceptional execution event translates to execution abort. This is why functions not have try..catch blocks everywhere where an exception could be thrown.
When an exception is thrown and not caught, the stack unwinds. This means that destructors will be called, everything will be cleaned up nicely. But consider this:
foo::~foo()
{
bar();
}
If we reach the destructor of foo because of an uncaught exception, and bar(); happens to throw, the application is immediately terminated, because C++ can not handle more than one exception at once.
This would not have happened if we, e.g. swallowed the exception:
foo::~foo()
{
try { bar(); } catch(...) { /* nom nom */ }
}
Update:
The first part refers to exception specifications like this:
struct foo
{
void bar() throw();
}
Valid syntax for this specification is
throw() // does not throw any exception
throw( list of exceptions ) // may throw one of these exceptions
throw(...) // may throw any exception
but as rodrigo mentioned, this turned out to be a bad idea, because these specifications led to dynamic checks (during runtime) whether an exception is thrown, significantly slowing down the performance.
In C++11 it is replaced by the noexcept keyword:
noexcept(true)
noexcept(false)
noexcept // identical to noexcept(true)
which is a guarantee that you give to the compiler, not the other way around.
But now finally to your question. When you give throw exception specification in some nested chain, and you throw an exception in a deeply nested function, you will have to update the signature of every function along the way. Another very good reason why exception specifications were stupid and should not be used anymore.
Exceptions specifications turned out to be a bad idea, and I think that they are deprecated in the latest revision of the language, so I'd just ignore it.
Generally speaking, destructors must not throw any exception. Because they are called during the stack unwinding that happens when an exception is thrown/catch. If an exception is thrown while the stack is unwinding, the program will abort. The easy/safe solution is to wrap the destructor body with a try {...} catch (..} {} block.
Related
Is it possible to make a destructor catch exceptions and then re-throw them?
If so, how would I do that, since there isn't a clear place for a try statement?
Basically, I want to ideally do:
CMyObject::~CMyObject()
{
catch(...) // Catch without a try. Possible?
{
LogSomeInfo();
throw; // re-throw the same exception
}
// Normal Destructor operations
}
Background
I have a large, complex application that is throwing an unhandled exception somewhere.
I don't have easy access to main or the top level message-pump or anything similar, so there's no easy place to catch all unhandled exceptions.
I figure any unhandled exception has to pass through a bunch of destructors as the stack is unwound. So, I'm contemplating scattering a bunch of catch statements in destructors. Then at least I'd know what objects are in play when the exception is thrown. But I have no idea if this is possible, or advisable.
EDIT: You can use std::uncaught_exception to check if an exception is currently being thrown (i.e. if stack unwinding is in progress due to an exception). It is not possible to catch that exception or otherwise get access to it from your destructor. So if your logging doesn't need access to the exception itself, you can use
CMyObject::~CMyObject()
{
if(std::uncaught_exception()) {
LogSomeInfo(); // No access to exception.
}
// Normal Destructor operations
}
Note that this question was asked in 2013, meanwhile std::uncaught_exception was replaced with std::uncaught_exceptions (notice the additional s at the end) which returns an int. For a rationale, see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4152.pdf, so if you are using C++17, you should prefer the new version. The above paper also explains why the old std::uncaught_exception will not work as expected in some situations.
Another option might be std::set_terminate. This is useful if you want to have a method called when an exception is not caught and about to terminate the program. In the terminate handler, I usually print some information about the exception and a (demangled) backtrace of where it originates from to my log file before finally terminating the program. This is compiler and system specific, but a real helper as it saves a lot of time if you write server processes and often the log file is all you get from ops.
You can use std::uncaught_exception() which returns true if and only if there is an exception being processed. It has been available since C++98, and is superseded by std::current_exception which returns a std::exception_ptr.
However you must be careful not to throw another exception in an unguarded context, otherwise std::terminate will be caught. Example:
X::~X() {
if (std::uncaught_exception()) {
try {
LogSomeInfo();
// and do something else...
} catch(...) {}
}
}
A destructor cannot catch the exception that is causing the destruction of the instance.
You can only know if there is any "active exception" (see uncaught_exception) during the destruction (or, in C++17, how many of them there are there with uncaught_exceptions) but it's possible that the exception(s) are indeed going to be handled after that.
Dealing with exceptions is very hard, much harder than someone may think at a first sight and the reason is that exception safety doesn't scale by composition. This in my opinion means that is basically impossible to have non trivial stateful subsystems with strong exception safety (in case of an exception being thrown nothing happened to the internal state). This was discovered long ago (see 1994 Tom Cargill's "Exception handling: A False Sense of Security") but apparently is still ignored by large part of the C++ community.
The only reasonable way to handle exceptions I can think to is to have subsystems with clear well defined interfaces with thick "walls" (no side effect happening inside may escape), and that can be re-initialized to a well known state from scratch if needed when something goes wrong. This not trivial but can be done correctly to a reasonable extent.
In all other cases the global state of the system when an exception is caught is indefinite at best at the point of catch and there are in my opinion few use cases in which you can do anything in such a condition except dying immediately as loudly as possible instead of taking further actions without indeed knowing what is going on (dead programs tell no lie). Even keeping on calling destructors is somewhat questionable in my opinion.
Or you may try to be as functional as possible, but that's not an easy path either (at least for my brain) and it's also moving far away from reality (most computers are mutable objects with many billions of bits of mutable state: you can pretend this is not the case and they're instead mathematical functions with no state and with predictable output dependent on input... but in my opinion you're just deluding yourself).
I know that I shouldn't throw exceptions from a destructor.
If my destructor calls a function that can throw an exception, is it OK if I catch it in the destructor and don't throw it further? Or can it cause abort anyway and I shouldn't call such functions from a destructor at all?
Yes, that's legal. An exception must not escape from the destructor, but whatever happens inside the destructor, or in functions it calls, is up to you.
(Technically, an exception can escape from a destructor call as well. If that happens during stack unwinding because another exception was thrown, std::terminate is called. So it is well-defined by the standard, but it's a really bad idea.)
Yes.
Look at the std::fstream class in the standard library for an example.
close() could potentially throw an exception.
The destroctor can call close() but the destructor does not throw (it will swallow any exceptions).
The concept is that if the destructor calls any methods that can throw then these methods should be public. Thus if the user of your object wants to check for exceptions they can use the public methods and handle the exception. If they do not care about the exception then just let the destructor handle the problem.
Going back to the std::fstream example.
{
std::fstream text("Plop");
// Load Text.
// I don't care if the close fails.
// So let the destructor handle it and discard exceptions
}
{
// If this fails to write I should at least warn the user.
// So in this case I will explicitly try and close it.
try
{
std::ofstram password("/etc/password");
// Update the password file.
password.close();
}
catch(...)
{
Message.ShowDialog("You failed to update the Password File");
}
}
You can find some examples here: https://software.intel.com/sites/products/documentation/doclib/iss/2013/sa-ptr/sa-ptr_win_lin/GUID-D2983B74-74E9-4868-90E0-D65A80F8F69F.htm
If an exception leaves destructor during stack unwinding of another exception being propagated, then std::terminate() is called.
When no stack unwinding is in progress, an exception can leave destructor without std::terminate() getting called. However, for objects allocated on heap this will result in memory leak because "operator delete" will not be called for the object who throws exception out of its destructor. Surprisingly, the destructor of base class still gets called in this case: What happens to base class destructor if a derived class destructor throws an exception
If the exception is catched inside the destructor (so that the exception does not leave the destructor), then no problem even if stack unwinding of another exception is in progress. This case is described more deeply here: http://bin-login.name/ftp/pub/docs/programming_languages/cpp/cffective_cpp/MEC/MI11_FR.HTM
Simple answer, never allow an exception from a dtor!
The complicated answer. You only get really nailed if the exception escapes the dtor while another exception is active. The normal case for this is when you are already unwinding the stack from another exception and the object in question is destroyed. In that case if the exception escapes the dtor then std::terminate is called, note you can put in your own handler for std::terminate by calling std::set_terminate. The default implementation of std::terminate is to call abort.
To complicate things more, most functions that want to make any guarantee about their exception safety, mainly the basic guarantee or the strong guarantee, rely on the underlying types to themselves not throw in their dtor*
The real question is, what state would your program be in when this error occurs? How can you recover? Where should this recovery be handled? You need to look at your specific case and work these issues out. Sometimes it's just fine to catch the exception and ignore it. Other times you need to raise some red flags.
So the answer is: it allowed by C++ to throw an exception in a dtor, but you shouldn't ever allow it to escape.
*Here's a brief synopsis of the exception guarantees (here's a much longer article)
Recap: Briefly define the Abrahams exception safety guarantees (basic,
strong, and nothrow).
The basic guarantee is that failed
operations may alter program state,
but no leaks occur and affected
objects/modules are still destructible
and usable, in a consistent (but not
necessarily predictable) state.
The strong guarantee involves
transactional commit/rollback
semantics: failed operations guarantee
program state is unchanged with
respect to the objects operated upon.
This means no side effects that affect
the objects, including the validity or
contents of related helper objects
such as iterators pointing into
containers being manipulated.
The nothrow guarantee means that
failed operations will not happen. The
operation will not throw an exception.
You may find this page from C++ FAQ Lite to be informative. The basic answer is, "don't do it." Where exactly do you plan to catch this exception? Whatever you plan on doing when you catch that exception, just do it with a function call instead or something (e.g. log it or set a flag to warn the user or whatever). Throwing exceptions from the destructor runs the risk of causing your entire program to terminate.
I know destructor shouldn't not throw exception.
http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.13
I have the following code :
~a()
{
cleanup();
}
// I do not expect exception being thrown in this function.
// If exception really happen, I know that it is something not recoverable.
void a::cleaup()
{
delete p;
}
In my static source code analysis, it complains that I shall call the cleanup function in this way :
~a()
{
try {
cleanup();
}
catch(...) {
// What to do? Print out some logging message?
}
}
// I do not expect exception being thrown in this function.
// If exception really happen, I know that it is something not recoverable.
void a::cleaup()
{
delete p;
}
I am not sure whether this is a good practice, to place try...catch block in destructor, whenever it calls functions. As :
(1) If cleanup function able to throw exception, I know something bad had happened. I prefer it to be fail-fast. That is, just let the whole system crash, and let the programmer debugs it.
(2) Overhead occur while entering and exiting try...catch block.
(3) The code look cumbersome, with a lot of try...catch block around classes' destructor.
I may miss out some other points, why try...catch block should be in place.
Thanks.
Since delete won't throw, neither will cleanup and as such there is no need to put the call in try-catch.
Since your static analysis tool is probably having a hard time figuring that out, perhaps you could help it out (it's only a guess though) by declaring cleanup as no-throw.
void cleanup() throw();
Maybe you can be more precise about your cleanup function. Does the cleanup() function throw an exception intentionally, if only in very rare circumstances? Then you should definitely handle the case in your destructor because, even if rare, exception-throwing is expected behavior of cleanup().
At the very least, your exception handling code could leave your program in a well-defined state that would allow you to end your program gracefully.
Or do you mean cleanup() may throw e.g. an OutOfMemoryException or another runtime exception that you never handle anywhere else? Then I would omit the exception handling in the destructor as well. In such unusual circumstances, your application could probably not run its error handling code anyway. You should do everything possible to make sure even such an exceptions gets reported or logged properly.
Edit:
Now that you have shown the implementation of cleanup, Neil has already answered your question. delete p must not throw, hence a::cleanup will not throw as long as p's destructor does not throw.
Surely the issue is really in the destructor of p. When, in cleanup(), you say
delete p;
delete itself cannot throw, therefore the exception must comne from p's destructor. It is in that destructor you need to worry about using a try block, not the one for a.
There's not usually any point in throwing an error due to memory allocation or deletion. It either works or not, and you can spend a ton of work handling silly errors without getting any benefit.
You might want to do this in specific cases but it's nor done much in practice and when there's question you usually want to use debugger or more full instrumentation.
Fundamentally, it is not safe to throw an exception whilst already handling an exception.
If your destructor is being called whilst the stack is unwinding, and another exception is thrown, then your thread can be terminated immediately on some systems such as Symbian; that your code was planning to catch the exception won't stop that termination - your code won't even be called. Your thread certainly will be terminated if your exception escapes the destructor.
So try {} catch(...) {} in a destructor is not portable and is certainly tricky.
The sound advice is never call code that could throw an exception in cleanup code such as destructors and any function that might be called from a destructor, such as 'cleanup()', 'close()' or 'release_something()'.
The original poster also queries the performance of try-catch. Early in the adoption of C++ exceptions, exception handling code was reasonably expensive; these days, your compiler almost certainly uses zero-cost exceptions, which means that an exception not thrown adds no runtime performance penalty to the code (but of course does slightly increase the binary size of the program).
I never use this, but exception safety purists will say that your cleanup() function may throw without you expecting it. So this pattern is a technique for extra safety.
However, a cleanup function should not throw in the first place. So I would put any exception handling inside cleanup(), not in the destructor itself.
I am not getting why if there is an active exception then if an exception is raised again, it leads to termination of program. Could someone explain?
What is it suppose to do? It can't "double catch" or anything, nor does it make sense to simply ignore one. The standard specifies that if, during stack unwinding, another exception escapes, then terminate shall be called.
There is more discussion in the C++ FAQ. One "solution" is to wrap your destructor code in a try/catch block, and simply don't let exceptions escape.
Another is to come up with some sort of custom exception chaining scheme. You'd do the above, but instead of ignoring an exception, you would append it to the currently thrown exception, and at the catch site handle both by hand.
The best solution, I think, it to try to remove the exceptional code from your destructor.
The reason is simple... if an exception is thrown during exception propagation, then which exception should be propagated? The original exception or the new exception? If the new exception is propagated and then handled, how will the program know that the other exception occurred? Or will the original exception be ignored? This and many other complications lead to the simple rule that only one exception may be propagated at a time, and multiple failures will result in the application being terminated.
Quoth the standard (15.2.3):
The process of calling destructors for automatic objects constructed on the path from a try block to a throw-expression is called ``stack unwinding.'' [Note: If a destructor called during stack unwinding exits with an exception, terminate is called (except.terminate). So destructors should generally catch exceptions and not let them propagate out of the destructor.
--- end note]
Basically C++ (as most other popular programming languages) has no good support for handling multiple errors using exceptions. Exceptions, as a mechanism, is simply deficient in that respect.
The FAQ has some suggestion on How to handle a destructor that fails?
Stroustroup has this to say on the matter (TCPL 14.7):
The reason for terminate() is that exception handling must occasionally be abandoned for less subtle error-handling techniques. For example, terminate() could be used to abort a process or maybe to re-initialize a system. The intent is for terminate() to be a drastic measure to applied when the error-recovery strategy implemented by the exception-handling mechanism has failed and it is time to go to another level of a fault tolerance strategy.
See also previous related discussion on SO: basically any question about exceptions and destructors.
This post has an explanation of the problem:
http://web.tiscali.it/fanelia/cpp-faq-en/exceptions.html#faq-17.3
When you throw an exception, it keeps unwinding the stack until it reaches an appropriate catch block. As part of the stack unwinding process, destructors are called for every object in each frame's scope.
Now, when a destructor throws an exception in this case, there's a dilemma -- which catch block is the program supposed to stop at? The original exception, or the new exception? Either way, there's an unprocessed exception involved.
Program's aren't good at making decisions like this, so the standard says it won't even try to resolve the issue and just gives up.
Check out the FAQ-Lite entry explaining this exact situation for further details.
Item 8 of Effective C++ says that you shouldn't ever allow an exception to leave a destructor.
It seems it is general accepted that exception specifications are not helping as much as one thinks. But I wonder if a specification which only uses std::exception might be a good compromise:
void someFunction()
throw ( std::exception );
It documents the fact that this method/function might throw an exception.
It would make sure that only exceptions derived from std::exception are thrown and not some exotic classes like std::string or int.
So, would this be better then not having any specification at all?
Update:
Regarding the Runtime-Overhead: Think of it like the usage of asserts. You are using asserts regardless of the runtime-overhead, right? I know you usually can disable them for a release-build, so maybe a better approach would be to wrap the exception specification in a macro so you can disable it for a release build. Something like:
#ifdef DEBUG
#define THROW( exception ) throw ( exception )
#else
#define THROW( exception )
#endif
void someFunction()
THROW( std::exception );
Yes but what do you expect to happen when something that is not derived from std::exception is thrown?
Would you like the application to terminate.
No stack unwinding not destructors being called to tidy up the code, just the application exiting.
The difference between Java and C++ exception specifications is that Java checks the specifications at compile-time. C++ on the other hand does all the checking at run-time. So by the time your specifications have been violated it is already too late.
Even in Java code there is a movement to stop to using them. What tends to happen there is at the start of the project the exception specifications are tightly defined. But as the code grows and becomes more complex the specifications are diluted to a more and more general form. This is because as the code grows more exceptions can be thrown and if they can not be handled immediately you need to modify the exception specifications of the whole call chain back to the point where they can be handled. (Note I am not a Java Expert but I do play in a mature Java code base).
The only exception specification (I think) that is worth much is the no throw specification. This does have a valid application (but you have to use it with the try/catch(...) block).
Also read Herb Sutters article:
And this thread on SO: Should I use an exception specifier in C++?
Exception specifications are essentially useless. Martin York already linked to Herb Sutter's post about them, but in short, you run up against the following problems:
They're ignored by MSVC, and
Their effect is nothing like in
Java. The specifications are checked
at runtime, causing a performance
hit, witout giving you the
compile-time validation you get in
Java. All you're saying is "Insert extra code, such that when an
exception is thrown, its type is inspected, and then
either throw it as normal, or call
unexpected() instead.
So all you're doing is making it harder to catch the exceptions that may be thrown, while at the same time slowing down your program. There really isn't much point.
On a conforming compiler, adding a non-empty exception specification generates the equivalent of a try/catch block around the function. Although it's possible to implement this in a way that has no run-time overhead, on some current compilers you do get an overhead.
So there may be a cost, and all you gain is that, if someFunction or something it calls raises on non-std::exception-derived exception, std::unexpected is called, rather than the unhandled exception mechanism.
So I guess my answer's 'No' :-)
I tipically would do this:
void someFunction() /* throw (std::exception) */;
The only effect of the throw statement in the function declaration is to modify its signature: a pointer to "void x()" and a pointer to "void x() throw y" are two different types.
In this way you are still documenting that the function might throw something, and you are losing nothing since the c++ compiler does not enforce any constraint anyway.