Search

14.2 — Basic exception handling

In the previous lesson on the need for exceptions, we talked about how using return codes causes your 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 as 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 any of the 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 any of the statements inside this try block throws an exception, 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 immediately following it, but may have multiple catch blocks listed in sequence.

Once an exception has been caught by the try block and routed to a catch block for handling, the exception is considered handled, and execution will resume as normal after the catch block.

Catch parameters work just like function parameters, with the parameter being available within the subsequent catch block. Exceptions of fundamental types can be caught by value, but exceptions of non-fundamental types should be caught by const reference to avoid making an unnecessary copy.

Just like with functions, if the parameter is not going to be used in the catch block, the variable name can be omitted:

This can help prevent compiler warnings about unused variables.

Putting throw, try, and catch together

Here’s a full program that uses throw, try, and multiple catch blocks:

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

We caught an int exception with value -1
Continuing on our merry way

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

Once the exception was handled, the program continued as normal after the catch blocks, printing “Continuing on our merry way”.

Recapping exception handling

Exception handling is actually quite simple, and the following two paragraphs cover most of what you need to remember 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 to find an enclosing try block -- we’ll discuss this in more detail next lesson). 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 handler matches. 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 “This never prints” is never printed, because the exception caused the execution path to jump immediately 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 const char*. Because we’re within a try block and a matching exception handler is found, control immediately transfers to the const 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.

What catch blocks typically do

If an exception is routed to a catch block, it is considered “handled” even if the catch block is empty. However, typically you’ll want your catch blocks to do something useful. There are three common things that catch blocks do when they catch an exception:

First, catch blocks may print an error (either to the console, or a log file).

Second, catch blocks may return a value or error code back to the caller.

Third, a catch block may throw another exception. Because the catch block is outside of the try block, the newly thrown exception in this case is not handled by the preceding try block -- it’s handled by the next enclosing try block.

14.3 -- Exceptions, functions, and stack unwinding
Index
14.1 -- The need for exceptions

27 comments to 14.2 — Basic exception handling

  • Mr C++

    "Third, a catch block may throw another exception. Because the catch block is outside of the try block, the newly thrown exception in this case is not handled by the preceding try block -- it’s handled by the next enclosing try block."
    Taking into consideration your this point, I tried to Do Something Like This :-

    But didn’t work as intended.
    Help Please 🙂
    Thanks in Advance !

    • Alex

      your throw “Exception not handled(1) !\n”; is not in an enclosing try block, so it’s not handled.

      This works:

      In the above, the re-throw is caught by the outer try block and routed to the lower catch block.

  • C++ Learner

    why there is written char parameter if the exception will be type double or type int?

    • Alex

      That example throws an exception of type const char*:

  • Sandeep

    Awesome and very helpful tutorials. Thanks a lot Alex.

  • Jiaan

    Just some small problems. In "Putting throw, try, and catch together" section, there are 2 instances  of "cerr" in the code, which should be "std::cerr". Also a space is missing between the string and x.

  • hello sir,

    It is very helpful tutorials keep on the good work .

  • Olli

    Alex, just wanting to let you know, these tutorials are really great : ) Kudos to You!

  • Ninja

    Hey Alex, I found a way to check if the user inputs a letter or string instead of a number. I made the user input a string and then converted it to a double using std::stod. Then I found out on the c++ website that if std::stod fails, it throws an object of std::invalid_argument (must include <stdexcept>). So I catch that exception and put out my own statement. Is there anything wrong with this approach?
    Here is my code.

    I found 1 issue actually. If the input starts with a number and then there are letters, it works. So if i write 9asefdas for input, the output will be 3. It ignores the rest for some reason. How do i fix that?
    and Happy New Year!

    • Alex

      std::stod() can take an optional second parameter: double stod (const string& str, size_t* idx = 0); See this page for more info. You can test whether the return value of this second parameter is equal to the strlen() of the input string. If so, then stod() parsed the entire string. If not, then there must be non-numeric values it couldn’t parse.

  • Matt

    I believe you’ve used the phrase "attached catch block" a few times within this chapter, but I am still unsure exactly what "attached" means in this context. Does the catch block(s) literally have to come directly after the try block, or can there be code in between?

  • Lokesh

    In the example in section "A more realistic example" - line 19:
    Using GCC 4.8.1 (-std=c++11) to compile the program and entering a negative number causes the program to crash with the following message:
    [code]
    terminate called after throwing an instance of ‘char const*’

    This application has requested the Runtime to terminate it in an unusual way.
    Please contact the application’s support team for more information.
    [code]
    However using Visual Studio doesn’t have this problem. My question is "some_string" is a literal constant of type <const char*> but how come the Visual Studio compiler is able to handle the exception of type <const char*> with a catch block of type <char*> ? Are the catch blocks strongly typed (there are no implicit type casting) or not ?

  • Himangshu

    Hi,
    In the last code snippet above,

    Should the return be a throw statement instead? Just a possible error, please clarify if I am missing out something. Thanks in advance.

  • 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.

  • cplususer

    /*program to show the concept of exception or error handling*/
    #include
    #include
    #include
    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
    //cout<<a<<endl;
    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;;
    count=count+1;
    if (count<=size)
    {
    goto ankur; //if count becomes greator than size then the condition will terminate and main will end here
    }
    else
    {
    exit(0);
    }
    }
    getch();
    }

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

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

  • Hamude

    Hi
    this tutorial is really great

  • 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.

Leave a Comment

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