Language Selector

15.2 — Basic exception handling

In the previous lesson on introduction to exceptions, we talked about how using return codes causes you control flow and error flow to be intermingled, constraining both. Exceptions in C++ are implemented using three keywords that work in conjunction with each other: throw, try, and catch.

Throwing exceptions

We use signals all the time in real life to note that particular events have occurred. For example, during American football, if a player has committed a foul, the referee will throw a flag on the ground and whistle the play dead. A penalty is then assessed and executed. Once the penalty has been taken care of, play generally resumes as normal.

In C++, a throw statement is used to signal that an exception or error case has occurred (think of throwing a penalty flag). Signaling that an exception has occurred is also commonly called raising an exception.

To use a throw statement, simply use the throw keyword, followed by a value of any data type you wish to use to signal that an error has occurred. Typically, this value will be an error code, a description of the problem, or a custom exception class.

Here are some examples:

Each of these statements acts a signal that some kind of problem that needs to be handled has occurred.

Looking for exceptions

Throwing exceptions is only one part of the exception handling process. Let’s go back to our American football analogy: once a referee has thrown a penalty flag, what happens next? The players notice that a penalty has occurred and stop play. The normal flow of the football game is disrupted.

In C++, we use the try keyword to define a block of statements (called a try block). The try block acts as an observer, looking for any exceptions that are thrown by statements within the try block.

Here’s an example of an try block:

Note that the try block doesn’t define HOW we’re going to handle the exception. It merely tells the program, “Hey, if you see an exception in the following code, grab it!”.

Handling exceptions

Finally, the end of our American football analogy: After the penalty has been called and play has stopped, the referee assesses the penalty and executes it. In other words, the penalty must be handled before normal play can resume.

Actually handling exceptions is the job of the catch block(s). The catch keyword is used to define a block of code (called a catch block) that handles exceptions for a single data type.

Here’s an example of a catch block:

Try blocks and catch blocks work together -- A try block detects any exceptions that are thrown by statements within the try block, and routes them to the appropriate catch block for handling. A try block must have at least one catch block attached to it, but may have multiple catch blocks listed in sequence:

Putting throw, try, and catch together

Running the above try/catch block would produce the following result:

We caught an exception of type int

A throw statement was used to raise an exception with the value -1, which is of type int. The try block routed the int exception to the catch block that handles exceptions of type int, which then printed the error message.

Exception handling behind the scenes

Let’s talk about what happens behind the scenes in a little more detail. Exception handling is actually quite simple, and the following two paragraphs are all you really need to know about it:

When an exception is raised (using throw), execution of the program immediately jumps to the nearest enclosing try block (propagating up the stack if necessary). If any of the catch handlers attached to the try block handle that type of exception, that handler is executed and the exception is considered handled.

If no appropriate catch handlers exist, execution of the program propagates to the next enclosing try block. If no appropriate catch handlers can be found before the end of the program, the program will fail with an exception error.

That’s really all there is to it. The rest of this chapter will be dedicated to showing examples of these principles at work.

Exceptions are handled immediately

Here’s a short program that demonstrates how exceptions are handled immediately:

This program is about as simple as it gets. Here’s what happens: the throw statement is the first statement that gets executed -- this causes an exception of type double to be raised. Execution immediately moves to the nearest enclosing try block, which is the only try block in this program. The catch handlers are then checked to see if any handlers matche. Our exception is of type double, so we’re looking for a catch handler of type double. We have one, so it executes.

Consequently, the result of this program is as follows:

We caught a double of value: 4.5

Note that the cout statement never executed, because the exception caused the execution path to change to the exception handler for doubles.

A more realistic example

Let’s take a look at an example that’s not quite so academic:

In this code, the user is asked to enter a number. If they enter a positive number, the if statement does not execute, no exception is thrown, and the square root of the number is printed. Because no exception is thrown in this case, the code inside the catch block never executes. The result is something like this:

Enter a number: 9
The sqrt of 9 is 3

If the user enters a negative number, we throw an exception of type char*. Because we’re within a try block and a matching exception handler is found, control immediately transfers to the char* exception handler. The result is:

Enter a number: -4
Error: Can not take sqrt of negative number

By now, you should be getting the basic idea behind exceptions. In the next lesson, we’ll do quite a few more examples to show how flexible exceptions are.

Multiple statements within a try block

In the lesson on the need for exceptions, we showed an example of one case where return codes don’t work very well:

In this code, ReadParameter() is returning a boolean value indicating success or failure. We end up having to check the return code from each call to ReadParameter() to ensure that it succeeded before proceeding. This leads to code that is messy and redundant.

Let’s rewrite this snippet of code using a new version of ReadParameter() throws an int exception on failure instead of returning a boolean value:

Note how much easier this is to read! If any of the calls to ReadParameter() throws an exception, that exception will be caught and routed to the int exception handler, which returns an error enum to the caller.

15.3 -- Exceptions, functions, and stack unwinding
15.1 -- The need for exceptions

14 comments to 15.2 — Basic exception handling

  • Kavitha

    Does the last example not require any THROW statement in the try block?Without that how would the try block know that an int value is thrown?

    • In the last example, the try block purposefully doesn’t throw anything, because it doesn’t really have any context to determine that something went wrong. Instead, it’s leaving it up to ReadParameter() to throw an exception if something went wrong. If ReadParameter() throws an int exception, the catch block will catch it and handle it.

  • kg

    in the sqrt program, both compilers I tried (g++4.3 & icpc11.0) made the throw statement of type char const*, so the catch statement would have to be

    for this exception to work properly

    just a heads up :)

    • Lubos

      or (const char *strException). char *const strException, otoh, doesn’t work - i assume strException is treated here as pointer to a constant “string”, not a constant pointer… right?

  • Hamude

    this tutorial is really great

  • Hamude

    what can the program sqrt do?

  • An excellent tutorial.
    for the catch with a string throw:

    have to be:

  • Gio

    Good tutorial! How would I catch a char or string that is entered where a double should be?

  • Hi alex,
    Nice tutorial, You have taken much more efforts to make this portal public… Examples are more realistic. and upto the mark.. :) :)

  • “see if any handlers matche(s).”

  • cplususer

    /*program to show the concept of exception or error handling*/
    void main()
    int count=1,size,a=0; //variable count and a are declared and initialized with count=1 and a=0
    cout<>size; //size of loop entered
    ankur: //jump statement body starts
    try //try body starts
    a=a+1; //value of a is incremented by 1 everytime when try body executes
    if (a%2==0) //condition starts if a is even then throw for even will executes otherwise throw of odd is executed
    { //in this no need to write the else statement because it's not required here
    throw ("Error! it's even");
    //cout<<"it's odd\n";
    throw("Error! it's odd"); //automatically if IF condition went wrong then this throw will exucute
    catch(char * ptr) //this keyword will work only with the help of char pointer variable and holds the string value of throw
    cout<<count<<". "<<ptr<<endl;;
    if (count<=size)
    goto ankur; //if count becomes greator than size then the condition will terminate and main will end here

  • Basim Alamuddin

    The first tutorial i have ever seen that teaches exceptions and start with the "throw" keyword, and i found it very logical. Thanks.

  • I am new at C++ programming. I understand exceptions happening due to the user entering data out of range but what about when a certain condition happens. Other things can happen that are not due to the user entering wrong information. I am new so I am trying to study code that is already written to understand how it works. What if someone reuses code and it is out of date? What about bugs and virus stuff? Exceptions can point to them also, right? Thanks for any input.

Leave a Comment




thirteen − ten =

Put C++ code inside [code][/code] tags to use the syntax highlighter