| Quick Introduction to C++ Exceptions |
|
|
| Written by Markus Ewald | |||
| Saturday, September 02 2006 18:05 | |||
|
The intent of this article is to provide a quick but complete introduction to C++ exceptions. The exception handling mechanism, common usage schemes and performance issues of exceptions versus return codes will all be covered. Let's take a look at why we want to at least inform ourselves about exceptions:
The ProblemThe average programmer commonly makes use of return codes to communicate the result of a function call back to the caller. There's nothing wrong with it, but it's just as common that a large portion of these return codes are not checked at all, sometimes because the programmer thought it was unlikely that a specific function might fail just there, sometimes also out of pure lazyness.
If an error goes by undetected, the program will be in an undefined state, doing strange
things or crashing in a place where it is next to impossible to locate the original error
which has caused the instability. To write robust code, all errors have to be detected and
properly handled (or returned to the caller if they cannot be handled in the current scope).
But doing so requires a lot of grunt work, littering each and every function with possibly
dozens of
Think of exceptions as an automation of this process. When an exception is thrown, the
current function automatically returns to its caller, which has the option to either catch
the exception, or to ignore it, causing the exception to travel further upward in the call
stack. Once the exception leaves the IntroductionExceptions aren't hard to master. Let's start with an example: What will happen here ?
Notice that the line of code, directly after the call to
This time, the program won't crash. The exception we've thrown is going to be caught
within Of course, a function containing an exception handler can call another function, which also contains an exception handler. Actually, you can even nest exception handlers directly:
You can see two new things here: A nested try block which will catch the exception that
is thrown before it reaches the outer try block, and another way to use the
Try commenting out this line and see what happens! Exception classes
The standard C++ library provides us with a set of exception classes, which is used by
the C++ library functions and which we can use in our own applications. These are made
available to your code by including the Some of the exception classes provided by the C++ standard library are:
There are more exception classes in the standard library which you can look up in your compiler's documentation.
There's nothing preventing you from creating your own exception classes, even the seperation
of
Both exceptions (
When using exception classes, always throw by value. Throwing an exception allocated
with Should you ever need to catch all exceptions, regardless of their type, there's a special argument for catch which allows you to do so: In the above example, new throws an exception because the amount of memory we're requesting is invalid. We can catch this exception without knowing its type. Using exceptionsNow that we know the mechanics of C++ exceptions, let's see how and where we can use them. An exception is thrown, as is indicated by its name, in exceptional situations. Exceptions should not be used to control normal program flow.
However, some programmers understand an exceptional situation as a situation in which the
application can not continue to run and has to be aborted. If that was what exceptions were
intended for, they would be nothing more than a fancy, but redundant implementation of
the C runtime's An exceptional situation is exceptional when the current scope cannot recover from it. For example, a function that is called to load a bitmap, the file name of which being provided as an argument, will reach an exceptional situation when the file does not exist. It can not resolve this error on its own, neither does it know whether this bitmap is unimportant and can be silently replaced by a white square. For the caller, this situation may not be that exceptional anymore. Maybe the user just selected an invalid file in the file selector and expects all but the entire program aborting, trashing all his previous work. From the programmer's side, this means that when the image is loaded, after being selected by the user, all exceptions relating to file accesses can be handled by displaying a little message box to the user and continuing normal program flow. Throw exceptions when an error (an exceptional situation) occurs which can not be handled in the current scope. This is the most important and also the only rule to remember. DrawbacksA place where you would not want to use exceptions is within tight loops that have to run as fast as possible. Even if no exception is thrown, an exception handler can slow down the speed of function calls and object construction a bit. This is because of the stack unwinding code which some compilers will generate. I know there are some programmers which see their entire application as one tight loop which has to run as fast as possible on every single line of code. I can't help those ;) When refactoring existing code to use exceptions, you have to be very careful not to create situations like this one:
If the
As an example, take the This does not mean that there's an inherent problem with exceptions, just that you should be careful when equipping projects with exception handling that have been built by an exception-unaware programmer using return codes originally.
|

