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.
Related
I recently learned that in C++ there is a single "slot" for an active exception and this raise some questions for me.
The example that I know is something like:
void f()
{
MyClass c;
throw MyException;
}
When we get to the throw the function immediately returns and then the exception starts looking for its matching catch. But let's say that during the return of f, when the destructor of c is called, suppose it throws another exception of type MyException2, in this case from what I understood the program always crashes because there is only one "slot" for an active exception so when MyException2 occurs there is a problem.
I would like to know if there is a reason for this specific approach since most other languages have some sort of stack and give a message like During handling of this exception this other exception occurred, with clear stack traces for both exceptions.
Is there a reason for this problem not being approached? Things like a stack of active exceptions and if MyException2 occurs while MyException1 is active then it will just resolve and then return to the handling of MyException1?
I'm sorry if I may not be familiar with the proper terms, this is a purely education question from someone who wishes to know more about the "guts" of the language out of pure fascination.
What you’re thinking about in, say, Python looks like
try: risky()
except Error as e:
some_cleanup(e)
also_risky() # raises OtherError
if still_unhappy(): raise
more_handling()
The corresponding code in C++ behaves the same way and does not automatically terminate:
try {risky();}
catch(const Error &e) {
some_cleanup(e);
also_risky(); // throws OtherError
if(still_unhappy()) throw;
more_handling();
}
The reason is that the original exception might or might not have been handled successfully (is more_handling necessary, or is it just part of retrying?). C++ makes the optimistic statement that it was, whereas by default Python 3 makes the pessimistic statement that the new exception is fallout from the old. C++ could of course provide a syntax to indicate the other choice, like Python does (raise new from None), but such an “associated exception” would be more difficult still to deal with in a static-typing context than exceptions already are, and one of the main motivations is absent since C++ expects the program to provide whatever backtrace-reporting mechanisms are desired.
The parallel is stronger if you consider destructors in both languages (especially in CPython where many of them are reliably invoked during stack unwinding): here, Python simply prints to standard error if a destructor throws, because to do otherwise would greatly complicate its internal resource management. C++ is actually more permissive in that a destructor can throw so long as it was not invoked directly by the unwinding mechanism; this is dangerous, but is occasionally used by experts to good effect. On the other hand, C++ most certainly does not consider writing to standard error a sufficient option for handling an exception, so if its resource management encounters such a problem, it’s all over.
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 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.
I have realized, after some reading, that in C++ the exceptions specification is considered a bad thing:
int f() throw(A, B); // bad because a lot of reasons
(some references: 1, 2, etc.)
What I have not understood is how to replace it. How can I tell to the f()'s caller that he must catch an exception?
How about
//throws: A if something is wrong
// B if something else is wrong
int f();
You don't. Not saying anything means it can throw anything.
I assume you have some Java background to ask this question. Compile-time exception checking was a Java experiment that failed. That's why you don't see it anywhere else.
The general rule for exception handling is: handle it where you can. This usually boils down to a try-catch at some very high level, where you basically tell the user whatever he was trying to do failed. It is very rare to be able to recover from an exception and continue the operation.
You should, of course, provide documentation what exceptions your function throws. I don't consider this to be a replacement for the throw specification (its purpose is very different). You should document the exceptions that your function throws and can be handled meaningfully by the caller, whereas the throw specification has to list any exceptions that may come out of this function (and the functions it calls).
You could replace it with an automated documentation tool.
Such tools often have the ability to nicely format which exceptions a method will throw, like the doxygen \exception command (or \throw or \throws). Assuming users of your code read documentation, they would be able to find out what exceptions to catch.
/**
* #exception A
* #exception B
*/
int f();
See this question for more useful info: How to document all exceptions a function might throw?
How can I tell to the f()'s caller that he must catch an exception?
That you think the caller must catch an exception indicates that there might be something wrong with your design. Are you using exceptions to signal a non-exceptional circumstance such as end of file?
Mandating the immediate callers to catch all possible exceptions is bad design. Example: The push_back member functions of the standard library containers allocate memory, which can fail. The designers of the library did not expect callers to wrap each and every push_back in a try/catch block. It doesn't make sense. Doing so would make the code much uglier, much harder to test. Besides, how would you recover from an out of memory condition? Handling this once, at a high level, is about all you can do.
I am writing some library functions that needs to do some error reporting. I want to use exceptions rather than return values.
I wrote my functions that throws int exceptions.
Eg:
if(strm->atEnd()){
// unexpected end of stream
throw -2;
}
My question is, is this method OK? Or should I throw a exception derived from std::exception?
In what way is throwing a std::exception better? (Other than being able to use catch(std::exception &e))
Is throwing int exceptions bad practice? (all throw int values are documented in doxygen comments)
I can't find any reason as to why (in this case) should I throw an object.
I would throw an exception based on std::exception.
throw std::runtime_error("unexpected end of stream")
I find this easier to catch, log, et cetera. It also allows the removal of a comment and a magic number from the code.
This message can then be sent to the end-user to give them a hope of fixing the problem.
Users and library consumers can't read the comments in code, and they are unlikely to know what '-2' means.
Exception are for exceptional behaviour. They're the last thing that you should worry about optimizing!
Donald Knuth said:
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil
Also, an object as exception may carry information about the error.
For example, you have an exception that means that a file cannot be read. If you throw an object exception, the object may carry the file name, which you cannot have with ints.
If the exception origin is unknown (deep in your stack) and no one catches it, it will be easier to debug the program if the exception is an object with proper information.
My question is, is this method OK?
Think about the readability. Wouldn't
throw CUnexpectedEndOfStream();
be more readable than
throw -2
?
And in a lot of cases wouldn't seeing an instance of CUnexpectedEndOfStream thrown in the debugger mean TONS more than -2. That's not to mention that CUnexpectedEndOfStream could store gobs of useful information about the problem such as say the file that couldn't be read and maybe more info on the nature of the problem.
Or should I throw a exception derived from std::exception?
Inheriting from std::exception may be helpful if that's how you choose to organize your other exceptions. It a convenient base class that client code can use. Also depending on the exception you may want to use std::runtime_error.
Is throwing int exceptions bad practice? (all throw int values are documented in doxygen comments)
Who said it was bad practice? Throwing exceptions is a great way to handle exceptional situations. Most of the exceptions I throw are because of something that could have been prevented by the client code doing what it was supposed to-- the user of my code violated the contract. But many other exceptional non-normal cases also exist like OS errors, disks filling up, etc. All the things that aren't part of your programs normal flow. More importantly, since they're not part of your program's normal flow, you don't need to worry about performance.
As an example, I once used exceptions to trigger that a certain message parsing failure occurred. However, I found that these parsing errors occurred frequently to the point where I started handling exceptions and fixing the problem input and reparsing. After a while, I realized that a more readable solution would be to fix the problem directly in the parsing code and stop treating it like an exceptional case. All the code that made parsing decisions was put back in one place and I wasn't throwing exceptions like a drunken sailor throws out curse words.
You should throw an exception derived from std::exception, e.g. std::runtime_error.
Most existing code assumes that an ordinary C++ exception is a std::exception, and anything else is a "hard exception" to be propagated up to a very high control level, like main.
For example, existing code will most probably not be able to log any reasonable message for your int. It will just be "unknown exception type".
Cheers & hth.,
Why don't you do this:
if(strm->atEnd()){
// unexpected end of stream
throw std::exception("-2");
}
throw -2 is bad because the type of -2 is neither std::exception nor derives from std::exception.
Or you should better write your own class as:
class FileException : public std::exception
{
//...
};
And then
throw FileException("Unexpected end of stream");
which is more readable.