Reputation: 2730
I was talking to a friend of mine that through my new code I didn't treat exceptions, just because I didn't know how to do it in C++. His answer surprised me: "why in the hell would you want to throw excetions?". I asked him why, but he didn't have a satisfying answer, so I googled it. One of the first pages I found was a blog entry, where the guy who posted wasn't totally against exceptions, but a religious war started in the replies: http://weblogs.asp.net/alex_papadimoulis/archive/2005/03/29/396141.aspx
Now I begin to wonder: is it that bad to throw an exception? For a student like I am, is it wrong to learn programming using exceptions as a normal thing? (When I throw exceptions, I catch them in another level of the code to treat them, most of the times). I have a code example, and I want to know what should I do:
int x;
cout << "Type an integer: ";
cin >> x;
Anything that is typed there that is not an integer will trigger an exception already, right? This exception should be treated there. But when I have a possible exception inside a class that is being used elsewhere in the program, should I make this method throw an exception so I can treat it wherever I call it or should I make it return a standard value when it has any problems?
The exception is always good, always bad, or something to be used in "exceptional" situations? Why?
Upvotes: 14
Views: 11092
Reputation: 48684
Throw an exception if, and only if, the alternative is failure to meet a post condition or to maintain an invariant.
That advice replaces an unclear subjective decision (is it a good idea) with a technical, precise question based on design decisions (invariant and post conditions) you should already have made.
Upvotes: 0
Reputation: 22624
I tend to follow this convention for internal parts of my applications code:
However when designing components, I do use component-scope exceptions, like for example, if connecting to a required database (one which is set up by the installer) fails. Or when you try to call any method violating its preconditions. In general, preconditions are expressed with assertions; however, in the public layer of your component, they should be checked and an exception thrown if they are violated, otherwise the caller has a hard job finding what they are doing wrong. (An alternative is of course to use a debug version, in which failed assertions will scream at you; but this is not always practical - distributing two binaries, keeping them up to date, etc.)
In my opinion, the only general rule is to be consistent and write correct code - choose some way to handle the erroneous/exceptional situations, and follow it consistently.
Upvotes: 1
Reputation: 264411
There is no reason not to use exceptions.
Whether to use exceptions or other techniques depends on the situation.
Exceptions are good to use when you can't fix the error locally.
(This should be an exceptional situation :-)
Error codes are good when you can fix the error locally.
Error codes are bad if you have a library that exposes an interface that returns an error code that needs to be manually checked. In the C world forgetting to check the error code was a significant source of problems.
Exceptions are good when you want to force the user of your interface to check for an error. If the user does not explicitly check and compensate; then the exception will propagate until either it is handled or the application exits.
Problems that come with exceptions:
If your code is a combination of C and C++. Functions with C ABI do not contain enough information for exceptions to propagate. Thus throwing an exception across a C function can (depending on the compiler and other factors) cause problems.
If you register a callback functions with a C library that uses C++ code. Then you must make sure that all exceptions are caught in the callback function and not allowed to propagate back to the C-library.
But this is true when combining any two languages. You can only use the most primitive features across language boundaries (and even that can take work if the languages do not align well). Therefore trying to use any advanced features is usually not supported.
C++ streams by default do not use exceptions.
This is because usually you want to handle the problem immediately.
In your example you use input as an example. In this situation you want to check the error and re-request the input.
int x;
cout << "Type an integer: ";
cin >> x;
while(!cin)
{
cin.clear();
std::cout << "Failed: What do you think an integer is? Try again: ";
cin >> x;
}
Personally I don't like the phrase 'Use exceptions in Exceptional circumstances". To me that is just to vague. vector::at() throws an exception. For me accessing off the end of an array is going to be exceptional (but for Joe student I doubt it will be exceptional (it will happen every second class as the lecturer throws a new curve ball at him/her)).
Thus I prefer the term "When the problem can not be fixed locally". A problem that can not be fixed locally is when something big has gone wrong (resource depletion (memory full throw bad_alloc()), coding error (access beyond array bounds (throw range_check()))) or any number of things that can not be fixed right there.
Upvotes: 15
Reputation: 815
This one is also a very interesting and controversial reading on the argument:
http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx
Upvotes: 0
Reputation: 95499
The C++ iostreams classes do not, by default, use exception handling. Generally one should use exceptions for situations where an error can occur, but such errors are "unusual" and "infrequent" (such as a disk failing, the network being down, etc.). For error conditions that you do expect (such as the user providing invalid input), you should probably not use exception handling, unless the logic that needs to deal with this situation is far removed from the logic in which the situation is detected, in which case using an exception is the way to go. There is nothing wrong with using exceptions, and using exceptions where they are merited is definitely good... just avoid using them where if...else works just fine.
As to the why:
Upvotes: 17
Reputation: 1484
I think exception handling/throwing can be boiled down to the following:
using
in C#, or with
in Python) so your code is exception safe.Consider a hypothetical example where you're using a serial port communication library to communicate with an external sensor of sorts. Furthermore:
If the serial port library thrown an exception, you can:
Option #1 is unlikely in most cases. And option #2 would probably not add any valuable information to what's already in the original exception.
So usually it's best to allow original exception to bubble up (this is again assuming the RAII is in place and no clean up is needed).
On the other hand, if the sensor itself reports an error code, then it makes a lot of sense to throw your own exception.
Upvotes: 0
Reputation: 25497
Read everything in Section 14 upto section 14.2 of Bjarne Stroustrup: "C++ programming Language Third Edition"
It is the most convincing answer I have come across.
Upvotes: -3
Reputation: 986
If you just blindly go and say I won't use exceptions it means you're not going to use most of the STL. That means you need to write your own classes for strings/vector etc etc ...
Plus exceptions are a much cleaner way of doing error handling (IMHO) and if you already do RAII then adding exceptions is not much harder.
Upvotes: -1
Reputation: 10453
There is actually a legitimate reason behind why you shouldn't use exceptions.
The problem is when you throw exception across boundaries (e.g. from one DLL and try...catch it in another DLL) sometimes things can go very wrong. I got a slap on the wrist too when I used it in one of my projects.
Just google it you'll find all sorts of post on this topic, at least it was a problem few years ago when I was still a fulltime C++ developer :)
Upvotes: 1