Bruno Machado - vargero
Bruno Machado - vargero

Reputation: 2730

To throw or not to throw exceptions?

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

Answers (9)

Raedwald
Raedwald

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

Daniel Daranas
Daniel Daranas

Reputation: 22624

I tend to follow this convention for internal parts of my applications code:

  • Do not throw exceptions of your own.
  • Catch any exception that could be expected from your calls to other code inmediately. Treat it accordingly, for example returning an error code, or "false" with the meaning of no success.

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

Loki Astari
Loki Astari

Reputation: 264411

Question 1:

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.

Question 2:

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;
}

Note:

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

Gianluca
Gianluca

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

Michael Aaron Safyan
Michael Aaron Safyan

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:

  1. Exceptions often provide a simple, elegant way of handling unexpected errors, but:
  2. Exception propagation, depending on the compiler and platform, may be slower than ordinary control flow, so if you can handle the situation locally, then that will be at least as fast... and you especially don't want to slow down the common, expected cases (such as invalid input). Also:
  3. Exceptions require more type information to be present and also require code that is unrelated to throwing or catching exceptions to be "exception-safe" which is why some object to exceptions.

Upvotes: 17

Mhmmd
Mhmmd

Reputation: 1484

I think exception handling/throwing can be boiled down to the following:

  • Use RAII (or using in C#, or with in Python) so your code is exception safe.
  • Catch exceptions if there's a chance to recover from the error, else let them bubble up.
  • Throw exception only if you have something useful to add.

Consider a hypothetical example where you're using a serial port communication library to communicate with an external sensor of sorts. Furthermore:

  • The serial port communication library reports errors by throwing exceptions.
  • The sensor itself can communicate certain error messages through status codes in cases when it's no longer able to acquire data, when it's functioning outside its max/min operating conditions, etc.
  • You're using RAII (Resource Acquisition Is Initialization), so if the serial port library throws an exception you wouldn't have to worry about releasing any acquired resources.

If the serial port library thrown an exception, you can:

  1. Catch the exception and try to recover from it somehow, e.g. by reinitializing the library.
  2. Catch the exception, wrap it in your own, and then throw the new exception up the call stack.

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

Chubsdad
Chubsdad

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

obelix
obelix

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

oscarkuo
oscarkuo

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

Related Questions