- Table of Contents
- Previous Chapter
- Next Chapter

# Chapter 10: Exceptions

C supports several ways for a program to react to situations breaking the normal unhampered flow of a program:

- The function may notice the abnormality and issue a message. This is probably the least disastrous reaction a program may show.
- The function in which the abnormality is observed may decide to stop its intended task, returning an error code to its caller. This is a great example of postponing decisions: now the calling function is faced with a problem. Of course the calling function may act similarly, by passing the error code up to its caller.
- The function may decide that things are going out of hand, and may call `exit` to terminate the program completely. A tough way to handle a problem if only because the destructors of local objects aren't activated.
- The function may use a combination of the functions `setjmp` and `longjmp` to enforce non-local exits. This mechanism implements a kind of `goto` jump, allowing the program to continue at an outer level, skipping the intermediate levels which would have to be visited if a series of returns from nested functions would have been used.

In C++ all these flow-breaking methods are still available. However, of the mentioned alternatives, `setjmp` and `longjmp` isn't frequently encountered in C++ (or even in C) programs, due to the fact that the program flow is completely disrupted.

C++ offers exceptions as the preferred alternative to, e.g., `setjmp` and `longjmp`. Exceptions allow C++ programs to perform a controlled non-local return, without the disadvantages of `longjmp` and `setjmp`.

Exceptions are the proper way to bail out of a situation which cannot be handled easily by a function itself, but which is not disastrous enough for a program to terminate completely. Also, exceptions provide a flexible layer of control between the short-range `return` and the crude `exit`.

In this chapter exceptions are covered. First an example is given of the different impact exceptions and the `setjmp/longjmp` combination have on programs. This example is followed by a discussion of the formal aspects of exceptions. In this part the guarantees our software should be able to offer when confronted with exceptions are presented. Exceptions and their guarantees have consequences for constructors and destructors. We'll encounter these consequences at the end of this chapter.

## 10.1: Exception syntax

Before contrasting the traditional C way of handling non-local gotos with exceptions let's introduce the syntactic elements that are involved when using exceptions.

- Exceptions are generated by a `throw` statement. The keyword `throw`, followed by an expression of a certain type, throws the expression value as an exception. In C++ anything having value semantics may be thrown as an exception: an `int`, a `bool`, a `string`, etc. However, there also exists a standard exception type (cf. section 10.8) that may be used as base class (cf. chapter 13) when defining new exception types.

- Exceptions are generated within a well-defined local environment, called a `try`-block. The run-time support system ensures that all of the program's code is itself surrounded by a global `try` block. Thus, every exception generated by our code will always reach the boundary of at least one `try`-block. A program terminates when an exception reaches the boundary of the global `try` block, and when this happens destructors of local and global objects that were alive at the point where the exception was generated are not called. This is not a desirable situation and therefore all exceptions should be generated within a `try`-block explicitly defined by the program. Here is an example of a string exception thrown from within a `try`-block:

      try
      {
          // any code can be defined here
          if (someConditionIsTrue)
              throw "this is the std::string exception"s;
          // any code can be defined here
      }

- `catch`: Immediately following the `try`-block, one or more `catch`-clauses must be defined. A `catch`-clause consists of a catch-header defining the type of the exception it can catch followed by a compound statement defining what to do with the caught exception:

      catch (string const &msg)
      {
          // statements in which the caught string object are handled
      }

  Multiple `catch` clauses may appear underneath each other, one for each exception type that has to be caught. In general the `catch` clauses may appear in any order, but there are exceptions requiring a specific order. To avoid confusion it's best to put a `catch` clause for the most general exception last. At most one exception clause will be activated. C++ does not support a Java-style `finally`-clause activated after completing a catch clause.

## 10.2: An example using exceptions

In the following examples the same basic program is used. The program uses two classes, `Outer` and `Inner`.

First, an `Outer` object is defined in `main`, and its member `Outer::fun` is called. Then, in `Outer::fun` an `Inner` object is defined. Having defined the `Inner` object, its member `Inner::fun` is called.

That's about it. The function `Outer::fun` terminates calling `inner`'s destructor. Then the program terminates, activating `outer`'s destructor. Here is the basic program:

        #include <iostream>
        using namespace std;

        class Inner
        {
            public:
                Inner();
                ~Inner();
                void fun();
        };
        Inner::Inner()
        {
            cout << "Inner constructor\n";
        }
        Inner::~Inner()
        {
            cout << "Inner destructor\n";
        }
        void Inner::fun()
        {
            cout << "Inner fun\n";
        }

        class Outer
        {
            public:
                Outer();
                ~Outer();
                void fun();
        };
        Outer::Outer()
        {
            cout << "Outer constructor\n";
        }
        Outer::~Outer()
        {
            cout << "Outer destructor\n";
        }
        void Outer::fun()
        {
            Inner in;
            cout << "Outer fun\n";
            in.fun();
        }

        int main()
        {
            Outer out;
            out.fun();
        }

        /*
            Generated output:
        Outer constructor
        Inner constructor
        Outer fun
        Inner fun
        Inner destructor
        Outer destructor
        */

After compiling and running, the program's output is entirely as expected: the destructors are called in their correct order (reversing the calling sequence of the constructors).

Now let's focus our attention on two variants in which we simulate a non-fatal disastrous event in the `Inner::fun` function. This event must supposedly be handled near `main`'s end.

We'll consider two variants. In the first variant the event is handled by `setjmp` and `longjmp`; in the second variant the event is handled using C++'s exception mechanism.

### 10.2.1: Anachronisms: `setjmp' and `longjmp'

The basic program from the previous section is slightly modified to contain a variable `jmp_buf jmpBuf` used by `setjmp` and `longjmp`.

The function `Inner::fun` calls `longjmp`, simulating a disastrous event, to be handled near `main`'s end. In `main` a target location for the long jump is defined through the function `setjmp`. `Setjmp`'s zero return indicates the initialization of the `jmp_buf` variable, in which case `Outer::fun` is called. This situation represents the `normal flow'.

The program's return value is zero only if `Outer::fun` terminates normally. The program, however, is designed in such a way that this won't happen: `Inner::fun` calls `longjmp`. As a result the execution flow returns to the `setjmp` function. In this case it does not return a zero return value. Consequently, after calling `Inner::fun` from `Outer::fun` `main`'s `if`-statement is entered and the program terminates with return value 1. Try to follow these steps when studying the following program source, which is a direct modification of the basic program given in section 10.2:

        #include <iostream>
        #include <setjmp.h>
        #include <cstdlib>

        using namespace std;

        jmp_buf jmpBuf;

        class Inner
        {
            public:
                Inner();
                ~Inner();
                void fun();
        };

        Inner::Inner()
        {
            cout << "Inner constructor\n";
        }
        void Inner::fun()
        {
            cout << "Inner fun\n";
            longjmp(jmpBuf, 0);
        }
        Inner::~Inner()
        {
            cout << "Inner destructor\n";
        }

        class Outer
        {
            public:
                Outer();
                ~Outer();
                void fun();
        };

        Outer::Outer()
        {
            cout << "Outer constructor\n";
        }
        Outer::~Outer()
        {
            cout << "Outer destructor\n";
        }
        void Outer::fun()
        {
            Inner in;
            cout << "Outer fun\n";
            in.fun();
        }

        int main()
        {
            Outer out;

            if (setjmp(jmpBuf) != 0)
                return 1;

            out.fun();
        }
        /*
            Generated output:
        Outer constructor
        Inner constructor
        Outer fun
        Inner fun
        Outer destructor
        */

This program's output clearly shows that `inner`'s destructor is not called. This is a direct consequence of the non-local jump performed by `longjmp`. Processing proceeds immediately from the `longjmp` call inside `Inner::fun` to `setjmp` in `main`. There, its return value is unequal zero, and the program terminates with return value 1. Because of the non-local jump `Inner::~Inner` is never executed: upon return to `main`'s `setjmp` the existing stack is simply broken down disregarding any destructors waiting to be called.

This example illustrates that the destructors of objects can easily be skipped when `longjmp` and `setjmp` are used and C++ programs should therefore avoid those functions like the plague.

### 10.2.2: Exceptions: the preferred alternative

Exceptions are C++'s answer to the problems caused by `setjmp` and `longjmp`. Here is an example using exceptions. The program is once again derived from the basic program of section 10.2:

        #include <iostream>
        using namespace std;

        class Inner
        {
            public:
                Inner();
                ~Inner();
                void fun();
        };
        Inner::Inner()
        {
            cout << "Inner constructor\n";
        }
        Inner::~Inner()
        {
            cout << "Inner destructor\n";
        }
        void Inner::fun()
        {
            cout << "Inner fun\n";
            throw 1;
            cout << "This statement is not executed\n";
        }

        class Outer
        {
            public:
                Outer();
                ~Outer();
                void fun();
        };

        Outer::Outer()
        {
            cout << "Outer constructor\n";
        }
        Outer::~Outer()
        {
            cout << "Outer destructor\n";
        }
        void Outer::fun()
        {
            Inner in;
            cout << "Outer fun\n";
            in.fun();
        }

        int main()
        {
            Outer out;
            try
            {
                out.fun();
            }
            catch (int x)
            {}
        }
        /*
            Generated output:
        Outer constructor
        Inner constructor
        Outer fun
        Inner fun
        Inner destructor
        Outer destructor
        */

`Inner::fun` now throws an `int` exception where a `longjmp` was previously used. Since `in.fun` is called by `out.fun`, the exception is generated within the `try` block surrounding the `out.fun` call. As an `int` value was thrown this value reappears in the `catch` clause beyond the `try` block.

Now `Inner::fun` terminates by throwing an exception instead of calling `longjmp`. The exception is caught in `main`, and the program terminates. Now we see that `inner`'s destructor is properly called. It is interesting to note that `Inner::fun`'s execution really terminates at the `throw` statement: The `cout` statement, placed just beyond the `throw` statement, isn't executed.

What did this example teach us?

- Exceptions provide a means to break a function's (and program's) normal flow without having to use a cascade of `return`-statements, and without the need to terminate the program using blunt tools like the function `exit`.
- Exceptions do not disrupt the proper activation of destructors. Since `setjmp` and `longjmp` do distrupt the proper activation of destructors their use is strongly deprecated in C++.

## 10.3: Throwing exceptions

Exceptions are generated by `throw` statements. The `throw` keyword is followed by an expression, defining the thrown exception value. Example:

        throw "Hello world";        // throws a char *
        throw 18;                   // throws an int
        throw string{ "hello" };    // throws a string

Local objects cease to exist when a function terminates. This is no different for exceptions.

Objects defined locally in functions are automatically destroyed once exceptions thrown by these functions leave these functions. This also happens to objects thrown as exceptions. However, just before leaving the function context the object is copied and it is this copy that eventually reaches the appropriate `catch` clause.

The following examples illustrates this process. `Object::fun` defines a local `Object toThrow`, that is thrown as an exception. The exception is caught in `main`. But by then the object originally thrown doesn't exist anymore, and `main` received a copy:

        #include <iostream>
        #include <string>
        using namespace std;

        class Object
        {
            string d_name;

            public:
                Object(string name)
                :
                    d_name(name)
                {
                    cout << "Constructor of " << d_name << "\n";
                }
                Object(Object const &other)
                :
                    d_name(other.d_name + " (copy)")
                {
                    cout << "Copy constructor for " << d_name << "\n";
                }
                ~Object()
                {
                    cout << "Destructor of " << d_name << "\n";
                }
                void fun()
                {
                    Object toThrow("'local object'");
                    cout << "Calling fun of " << d_name << "\n";
                    throw toThrow;
                }
                void hello()
                {
                    cout << "Hello by " << d_name << "\n";
                }
        };

        int main()
        {
            Object out{ "'main object'" };
            try
            {
                out.fun();
            }
            catch (Object o)
            {
                cout << "Caught exception\n";
                o.hello();
            }
        }

`Object`'s copy constructor is special in that it defines its name as the other object's name to which the string `" (copy)"` is appended. This allow us to monitor the construction and destruction of objects more closely. `Object::fun` generates an exception, and throws its locally defined object. Just before throwing the exception the program has produced the following output:

        Constructor of 'main object'
        Constructor of 'local object'
        Calling fun of 'main object'

When the exception is generated the next line of output is produced:

        Copy constructor for 'local object' (copy)

The local object is passed to `throw` where it is treated as a value argument, creating a copy of `toThrow`. This copy is thrown as the exception, and the local `toThrow` object ceases to exist. The thrown exception is now caught by the `catch` clause, defining an `Object` value parameter. Since this is a value parameter yet another copy is created. Thus, the program writes the following text:

        Destructor of 'local object'
        Copy constructor for 'local object' (copy) (copy)

The `catch` block now displays:

        Caught exception

Following this `o`'s `hello` member is called, showing us that we indeed received a copy of the copy of the original `toThrow` object:

        Hello by 'local object' (copy) (copy)

Then the program terminates and its remaining objects are now destroyed, reversing their order of creation:

        Destructor of 'local object' (copy) (copy)
        Destructor of 'local object' (copy)
        Destructor of 'main object'

The copy created by the `catch` clause clearly is superfluous. It can be avoided by defining object reference parameters in `catch` clauses: ``catch (Object &o)`'. The program now produces the following output:

        Constructor of 'main object'
        Constructor of 'local object'
        Calling fun of 'main object'
        Copy constructor for 'local object' (copy)
        Destructor of 'local object'
        Caught exception
        Hello by 'local object' (copy)
        Destructor of 'local object' (copy)
        Destructor of 'main object'

Only a single copy of `toThrow` was created.

It's a bad idea to throw a pointer to a locally defined object. The pointer is thrown, but the object to which the pointer refers ceases to exist once the exception is thrown. The catcher receives a wild pointer. Bad news....

Let's summarize the above findings:

- Local objects are thrown as copied objects;
- Don't throw pointers to local objects;
- It is possible to throw pointers to dynamically generated objects. In this case one must take care that the generated object is properly deleted by the exception handler to prevent a memory leak.

Exceptions are thrown in situations where a function can't complete its assigned task, but the program is still able to continue. Imagine a program offering an interactive calculator. The program expects numeric expressions, which are evaluated. Expressions may show syntactic errors or it may be mathematically impossible to evaluate them. Maybe the calculator allows us to define and use variables and the user might refer to non-existing variables: plenty of reasons for the expression evaluation to fail, and so many reasons for exceptions to be thrown. None of those should terminate the program. Instead, the program's user is informed about the nature of the problem and is invited to enter another expression. Example:

        if (!parse(expressionBuffer))           // parsing failed
            throw "Syntax error in expression";

        if (!lookup(variableName))              // variable not found
            throw "Variable not defined";

        if (divisionByZero())                   // unable to do division
            throw "Division by zero is not defined";

Where these `throw` statements are located is irrelevant: they may be found deeply nested inside the program, or at a more superficial level. Furthermore, functions may be used to generate the exception to be thrown. An `Exception` object might support stream-like insertion operations allowing us to do, e.g.,

        if (!lookup(variableName))
            throw Exception() << "Undefined variable '" << variableName << "';

### 10.3.1: The empty `throw' statement

Sometimes it is required to inspect a thrown exception. An exception catcher may decide to ignore the exception, to process the exception, to rethrow it after inspection or to change it into another kind of exception. For example, in a server-client application the client may submit requests to the server by entering them into a queue. Normally every request is eventually answered by the server. The server may reply that the request was successfully processed, or that some sort of error has occurred. On the other hand, the server may have died, and the client should be able to discover this calamity, by not waiting indefinitely for the server to reply.

In this situation an intermediate exception handler is called for. A thrown exception is first inspected at the middle level. If possible it is processed there. If it is not possible to process the exception at the middle level, it is passed on, unaltered, to a more superficial level, where the really tough exceptions are handled.

By placing an empty `throw` statement in the exception handler's code the received exception is passed on to the next level that might be able to process that particular type of exception. The rethrown exception is never handled by one of its neighboring exception handlers; it is always transferred to an exception handler at a more superficial level.

In our server-client situation a function

        initialExceptionHandler(string &exception)

could be designed to handle the `string` exception. The received message is inspected. If it's a simple message it's processed, otherwise the exception is passed on to an outer level. In `initialExceptionHandler`'s implementation the empty `throw` statement is used:

        void initialExceptionHandler(string &exception)
        {
            if (!plainMessage(exception))
                throw;

            handleTheMessage(exception);
        }

Below (section 10.5), the empty `throw` statement is used to pass on the exception received by a `catch`-block. Therefore, a function like `initialExceptionHandler` can be used for a variety of thrown exceptions, as long as their types match `initialExceptionHandler`'s parameter, which is a string.

The next example jumps slightly ahead, using some of the topics covered in chapter 14. The example may be skipped, though, without loss of continuity.

A basic exception handling class can be constructed from which specific exception types are derived. Suppose we have a class `Exception`, having a member function `ExceptionType Exception::severity`. This member function tells us (little wonder!) the severity of a thrown exception. It might be `Info, Notice, Warning, Error` or `Fatal`. The information contained in the exception depends on its severity and is processed by a function `handle`. In addition, all exceptions support a member function like `textMsg`, returning textual information about the exception in a `string`.

By defining a polymorphic function `handle` it can be made to behave differently, depending on the nature of a thrown exception, when called from a basic `Exception` pointer or reference.

In this case, a program may throw any of these five exception types. Assuming that the classes `Message` and `Warning` were derived from the class `Exception`, then the `handle` function matching the exception type will automatically be called by the following exception catcher:

        //
        catch (Exception &ex)
        {
            cout << e.textMsg() << '\n';

            if
            (
                ex.severity() != ExceptionType::Warning
                &&
                ex.severity() != ExceptionType::Message
            )
                throw;              // Pass on other types of Exceptions

            ex.handle();            // Process a message or a warning
        }

Now anywhere in the `try` block preceding the exception handler `Exception` objects or objects of one of its derived classes may be thrown. All those exceptions will be caught by the above handler. E.g.,

        throw Info{};
        throw Warning{};
        throw Notice{};
        throw Error{};
        throw Fatal{};

## 10.4: The try block

The `try`-block surrounds `throw` statements. Remember that a program is always surrounded by a global `try` block, so `throw` statements may appear anywhere in your code. More often, though, `throw` statements are used in function bodies and such functions may be called from within `try` blocks.

A `try` block is defined by the keyword `try` followed by a compound statement. This block, in turn, must be followed by at least one `catch` handler:

        try
        {
                    // any statements here
        }
        catch (...)  // at least one catch clause here
        {}

`Try`-blocks are commonly nested, creating exception levels. For example, `main`'s code is surrounded by a `try`-block, forming an outer level handling exceptions. Within `main`'s `try`-block functions are called which may also contain `try`-blocks, forming the next exception level. As we have seen (section 10.3.1), exceptions thrown in inner level `try`-blocks may or may not be processed at that level. By placing an empty `throw` statement in an exception handler, the thrown exception is passed on to the next (outer) level.

## 10.5: Catching exceptions

A `catch` clause consists of the keyword `catch` followed by a parameter list defining one parameter specifying type and (parameter) name of the exception caught by that particular `catch` handler. This name may then be used as a variable in the compound statement following the `catch` clause. Example:

        catch (string &message)
        {
            // code to handle the message
        }

Primitive types and objects may be thrown as exceptions. It's a bad idea to throw a pointer or reference to a local object, but a pointer to a dynamically allocated object may be thrown if the exception handler deletes the allocated memory to prevent a memory leak. Nevertheless, throwing such a pointer is dangerous as the exception handler won't be able to distinguish dynamically allocated memory from non-dynamically allocated memory, as illustrated by the next example:

        try
        {
            static int x;
            int *xp = &x;

            if (condition1)
                throw xp;

            xp = new int(0);
            if (condition2)
                throw xp;
        }
        catch (int *ptr)
        {
            // delete ptr or not?
        }

Close attention should be paid to the nature of the parameter of the exception handler, to make sure that when pointers to dynamically allocated memory are thrown the memory is returned once the handler has processed the pointer. In general pointers should not be thrown as exceptions. If dynamically allocated memory must be passed to an exception handler then the pointer should be wrapped in a smart pointer, like `unique_ptr` or `shared_ptr` (cf. sections 18.3 and 18.4).

Multiple `catch` handlers may follow a `try` block, each handler defining its own exception type. The order of the exception handlers is important. When an exception is thrown, the first exception handler matching the type of the thrown exception is used and remaining exception handlers are ignored. Eventually at most one exception handler following a `try`-block is activated. Normally this is of no concern as each exception has its own unique type.

Example: if exception handlers are defined for `char *`s and `void *`s then NTBSs are caught by the former handler. Note that a `char *` can also be considered a `void *`, but the exception type matching procedure is smart enough to use the `char *` handler with the thrown NTBS. Handlers should be designed very type specific to catch the correspondingly typed exception. For example, `int`-exceptions are not caught by `double`-catchers, `char`-exceptions are not caught by `int`-catchers. Here is a little example illustrating that the order of the catchers is not important for types not having any hierarchal relationship to each other (i.e., `int` is not derived from `double`; `string` is not derived from an NTBS):

    #include <iostream>
    using namespace std;

    int main()
    {
        while (true)
        {
            try
            {
                string s;
                cout << "Enter a,c,i,s for ascii-z, char, int, string "
                                                          "exception\n";
                getline(cin, s);
                switch (s[0])
                {
                    case 'a':
                        throw "ascii-z";
                    case 'c':
                        throw 'c';
                    case 'i':
                        throw 12;
                    case 's':
                        throw string{};
                }
            }
            catch (string const &)
            {
                cout << "string caught\n";
            }
            catch (char const *)
            {
                cout << "ASCII-Z string caught\n";
            }
            catch (double)
            {
                cout << "isn't caught at all\n";
            }
            catch (int)
            {
                cout << "int caught\n";
            }
            catch (char)
            {
                cout << "char caught\n";
            }
        }
    }

Rather than defining specific exception handlers a specific class can be designed whose objects contain information about the exception. Such an approach was mentioned earlier, in section 10.3.1. Using this approach, there's only one handler required, since we know we don't throw other types of exceptions:

        try
        {
            // code throws only Exception objects
        }
        catch (Exception &ex)
        {
            ex.handle();
        }

When the code of an exception handler has been processed, execution continues beyond the last exception handler directly following the matching `try`-block (assuming the handler doesn't itself use flow control statements (like `return` or `throw`) to break the default flow of execution). The following cases can be distinguished:

- If no exception was thrown within the `try`-block no exception handler is activated, and execution continues from the last statement in the `try`-block to the first statement beyond the last `catch`-block.
- If an exception was thrown within the `try`-block but neither the current level nor another level contains an appropriate exception handler, the program's default exception handler is called, aborting the program.
- If an exception was thrown from the `try`-block and an appropriate exception handler is available, then the code of that exception handler is executed. Following that, the program's execution continues at the first statement beyond the last `catch`-block.

All statements in a `try` block following an executed `throw`-statement are ignored. However, objects that were successfully constructed within the `try` block before executing the `throw` statement are destroyed before any exception handler's code is executed.

### 10.5.1: The default catcher

At a certain level of the program only a limited set of handlers may actually be required. Exceptions whose types belong to that limited set are processed, all other exceptions are passed on to exception handlers of an outer level `try` block.

An intermediate type of exception handling may be implemented using the default exception handler, which must be (due to the hierarchal nature of exception catchers, discussed in section 10.5) placed beyond all other, more specific exception handlers.

This default exception handler cannot determine the actual type of the thrown exception and cannot determine the exception's value but it may execute some statements, and thus do some default processing. Moreover, the caught exception is not lost, and the default exception handler may use the empty `throw` statement (see section 10.3.1) to pass the exception on to an outer level, where it's actually processed. Here is an example showing this use of a default exception handler:

        #include <iostream>
        using namespace std;

        int main()
        {
            try
            {
                try
                {
                    throw 12.25;    // no specific handler for doubles
                }
                catch (int value)
                {
                    cout << "Inner level: caught int\n";
                }
                catch (...)
                {
                    cout << "Inner level: generic handling of exceptions\n";
                    throw;
                }
            }
            catch (double d)
            {
                cout << "Outer level may use the thrown double: " << d << '\n';
            }
        }
        /*
            Generated output:
        Inner level: generic handling of exceptions
        Outer level may use the thrown double: 12.25
        */

The program's output illustrates that an empty `throw` statement in a default exception handler throws the received exception to the next (outer) level of exception catchers, keeping type and value of the thrown exception.

Thus, basic or generic exception handling can be accomplished at an inner level, while specific handling, based on the type of the thrown expression, can be provided at an outer level. Additionally, particularly in multi-threaded programs (cf. chapter 20), thrown exceptions can be transferred between threads after converting `std::exception` objects to `std::exception_ptr` objects. This proceduce can even be used from inside the default catcher. Refer to section 10.9.4 for further coverage of the class `std::exception_ptr`.

## 10.6: Functions unable to throw exceptions: the `noexcept' keyword

Once a function has been defined it's often called from other functions. If called functions are not defined in the same source file as calling functions the called functions must be declared, for which header files are often used. Those called functions might throw exceptions, which might be unacceptible to the function calling those other functions. E.g., functions like `swap` and destructors may not throw exceptions.

Functions that may not throw exceptions can be declared and defined by specifying the `noexcept` keyword (see section 10.9 for examples of function declarations specifying `noexcept`).

When using `noexept` there's a slight run-time overhead penalty because the function needs an over-all `try-catch` block catching any exception that might be thrown by its (called) code. When an exception is caught (violating the `noexcept` specification) then the `catch` clause calls `std::terminate`, ending the program.

In addition to using a plain `noexcept`, it can also be given an argument that is evaluated compile-time (e.g., `void fun() noexcept(sizeof(int) == 4)`): if the evaluation returns `true` then the `noexcept` requirement is used; if the evaluation returns `false`, then the `noexcept` requirement is ignored. Examples of this advanced use of `noexcept` are provided in section 23.8.

## 10.7: Iostreams and exceptions

The C++ I/O library was used well before exceptions were available in C++. Hence, normally the classes of the iostream library do not throw exceptions. However, it is possible to modify that behavior using the `ios::exceptions` member function. This function has two overloaded versions:

- `ios::iostate exceptions()`:
  this member returns the state flags for which the stream will throw exceptions;
- `void exceptions(ios::iostate state)`
  this member causes the stream to throw an exception when state `state` is observed.

In the I/O library, exceptions are objects of the class `ios::failure`, derived from `ios::exception`. A `std::string const &message` may be specified when defining a `failure` object. Its message may then be retrieved using its `virtual char const *what() const` member.

Exceptions should be used in exceptional circumstances. Therefore, we think it is questionable to have stream objects throw exceptions for fairly normal situations like `EOF`. Using exceptions to handle input errors might be defensible (e.g., in situations where input errors should not occur and imply a corrupted file) but often aborting the program with an appropriate error message would probably be the more appropriate action. As an example consider the following interactive program using exceptions to catch incorrect input:

        #include <iostream>
        #include <climits>
        using namespace::std;

        int main()
        {
            cin.exceptions(ios::failbit);   // throw exception on fail
            while (true)
            {
                try
                {
                    cout << "enter a number: ";
                    int value;
                    cin >> value;
                    cout << "you entered " << value << '\n';
                }
                catch (ios::failure const &problem)
                {
                    cout << problem.what() << '\n';
                    cin.clear();
                    cin.ignore(INT_MAX, '\n');  // ignore the faulty line
                }
            }
        }

By default, exceptions raised from within `ostream` objects are caught by these objects, which set their `ios::badbit` as a result. See also the paragraph on this issue in section 14.8.

## 10.8: Standard exceptions

All data types may be thrown as exceptions. Several additional exception classes are now defined by the C++ standard. Before using those additional exception classes the `<stdexcept>` header file must be included.

All of these standard exceptions are class types by themselves, but also offer all facilities of the `std::exception` class and objects of the standard exception classes may also be considered objects of the `std::exception` class.

The `std::exception` class offers the member

        char const *what() const;

describing in a short textual message the nature of the exception.

C++ defines the following standard exception classes:

- `std::bad_alloc` (this requires the `<new>` header file): thrown when `operator new` fails;
- `std::bad_array_new_length` (this requires the `<new>` header file): thrown when an illegal array size is requested when using `new Type[...]`. Illegal sizes are negative values, values that exceed an implementation defined maximum, the number of initializer clauses exceeds the specified number of array elements (e.g., `new int[2]{ 1, 2, 3 }`);
- `std::bad_cast` (this requires the `<typeinfo>` header file): thrown in the context of polymorphism (see section 14.6.1);
- `std::bad_exception` (this requires the `<exception>` header file): thrown when a function tries to generate another type of exception than declared in its function throw list;
- `std::bad_typeid` (this requires the `<typeinfo>` header file): also thrown in the context of polymorphism (see section 14.6.2);

All additional exception classes were derived from `std::exception`. The constructors of all these additional classes accept `std::string const &` arguments summarizing the reason for the exception (retrieved by the `exception::what` member). The additionally defined exception classes are:

- `std::domain_error`: a (mathematical) domain error is detected;
- `std::invalid_argument`: the argument of a function has an invalid value;
- `std::length_error`: thrown when an object would have exceeded its maximum permitted length;
- `std::logic_error`: a logic error should be thrown when a problem is detected in the internal logic of the program. Example: a function like C's `printf` is called with more arguments than there are format specifiers in its format string;
- `std::out_of_range`: thrown when an argument exceeds its permitted range. Example: thrown by `at` members when their arguments exceed the range of admissible index values;
- `std::overflow_error`: an overflow error should be thrown when an arithmetic overflow is detected. Example: dividing a value by a very small value;
- `std::range_error`: a range error should be thrown when an internal computation results in a value exceeding a permissible range;
- `std::runtime_error`: a runtime error should be thrown when a problem is encountered that can only be detected while the program is being executed. Example: a non-integral is entered when the program's input expects an integral value.
- `std::underflow_error`: an underflow error should be thrown when an arithmetic underflow is detected. Example: dividing a very small value by a very large value.
- `std::tx_exception<Type>`: derived from `std::runtime_error`. This exception can be thrown from an `atomic_cancel` compound statement (cf. section 20.14) to undo statements executed so far.

### 10.8.1: Standard exceptions: to use or not to use?

Since values of any type may be thrown as exceptions, you may wonder when to throw values of standard exception types and (if ever) when to throw values of other types.

Current practice in the C++ community is to throw exceptions only in exceptional situations. In that respect C++'s philosophy about using exceptions differs markedly from the way exceptions are used in, e.g., Java, where exceptions are often encountered in situations C++ doesn't consider exceptional. Another common practice is to follow a `conceptual' style when designing software. A nice characteristic of exceptions is that exceptions can be thrown at a point where your source shows what's happening: throwing an `std::out_of_range` exception is nice for the software maintainer, as the reason for the exception is immediately recognized.

At the catch-clause the semantical context usually isn't very relevant anymore and by catching a std::exception and showing its `what()` content the program's user is informed about what happened.

But throwing values of other types can also be useful. What about a situation where you want to throw an exception and catch it at some shallow level? In between there may be various levels of software provided by external software libraries over which the software engineer has no control. At those levels exceptions (std::exceptions) could be generated too, and those exceptions might also be caught by the library's code. When throwing a standard exception type it may be hard to convince yourself that that exception isn't caught by the externally provided software. Assuming that no catch-alls are used (i.e., `catch (...)`) then throwing an exception from the `std::exception` family might not be a very good idea. In such cases throwing a value from a simple, maybe empty, `enum` works fine:

        enum HorribleEvent
        {};

        ... at some deep level:
            throw HorribleEvent{};

        ... at some shallow level:
        catch (HorribleEvent hs)
        {
            ...
        }

Other examples can easily be found: design a class holding a message and an error (exit) code: where necessary throw an object of that class, catch it in the catch clause of main's try block and you can be sure that all objects defined at intermediate levels are neatly destroyed, and at the end you show the error message and return the exit code embedded in your non-exception object.

So, the advice is to use `std::exception` types when available, and clearly do the required job. But if an exception is used to simply bail out of an unpleasant situation, or if there's a chance that externally provided code might catch `std:exceptions` then consider throwing objects or values of other types.

## 10.9: System error, error_category, and error_condition

The class `std::system_error` is derived from `std::runtime_error`, which in turn is derived from `std::exception`

Before using the class `system_error` or related classes the `<system_error>` header file must be included.

`System_error` exceptions can be thrown when errors occur having associated (system) error values. Such errors are typically associated with low-level (like operating system) functions, but other types of errors (e.g., bad user input, non-existing requests) can also be handled.

In addition to error codes (cf. section 4.3.1) and error categories (covered below) error conditions are distinguished. Error conditions specify platform independent types of errors like syntax errors or non-existing requests.

When constructing `system_error` objects error codes and error categories may be specified. First we'll look at the classes `error_condition` and `error_category`, then `system_error` itself is covered in more detail.

Figure 9 illustrates how the various components interact.

Figure 9: System_error: associated components

As shown in figure 9 the class `error_category` uses the class `error_condition` and the class `error_condition` uses the class `error_category`. As a consequence of this circular dependency between these two classes these classes should be approached as one single class: when covering `error_category` the class `error_condition` should be known and vice versa. This circular dependency among these classes is unfortunate and an example of bad class design.

As `system_error` is eventually derived from `exception` it offers the standard `what` member. It also contains an `error_code`.

In POSIX systems the `errno` variable is associated with many, often rather cryptic, symbols. The predefined `enum class errc` attempts to provide intuitively more appealing symbols. Since its symbols are defined in a strongly typed enumeration, they cannot directly be used when defining a matching `error_code`. Instead, a `make_error_code` function converts `enum class errc` values and values of newly defined error code enumerations (called `ErrorCodeEnum` below) to `error_code` objects.

The `enum class errc` defined in the `std` namespace defines symbols whose values are equal to the traditional error code values used by C but describe the errors in a less cryptic way. E.g.,

        enum class errc
        {
            address_family_not_supported, // EAFNOSUPPORT
            address_in_use,               // EADDRINUSE
            address_not_available,        // EADDRNOTAVAIL
            already_connected,            // EISCONN
            argument_list_too_long,       // E2BIG
            argument_out_of_domain,       // EDOM
            bad_address,                  // EFAULT
            ...
        };

Values of `ErrorCodeEnums` can be passed to matching `make_error_code` functions. Defining your own `ErrorCodeEnum` enumeration is covered in section 23.7.

Now that the general outline has been presented, it's time to have a closer look at the various components shown in figure 9.

### 10.9.1: The class `std::error_category'

Objects of the class `std::error_category` identify sources of sets of error codes. New error categories for new error code enumerations can also be defined (cf. section 23.7).

Error categories are designed as singletons: only one object of each class can exist. Because of this `error_categories` are equal when the addresses of `error_category` objects are equal. Error category objects are returned by functions (see below) or by static `instance()` members of error category classes.

Error category classes define several members. Most are declared virtual (cf. chapter 14), meaning that those members may be redefined in error category classes we ourselves design:

- `virtual error_condition default_error_condition(int ev) const noexcept`:
  returns an `error_condition` object (cf. section 10.9.2) initialized with error value `ev` and the current (i.e., `*this`) `error_category`;

- `virtual bool equivalent(error_code const &code, int condition) const noexcept`:
  returns `true` if the equivalence between the error condition that is associated with the `error_code` object and the `error_condition_enum` value that is specified (as an `int` value) as the function's second argument could be establisted;

- `virtual bool equivalent(int ev, error_condition const &condition) const noexcept`:
  returns `true` if the equivalence of an `error_condition` object that is constructed from the `ErrorConditionEnum` value that is associated with the `ErrorCategoryEnum` value that was passed (as `int`) to the function and the `error_condition` object that was passed to the function as its second argument could be established;

- `virtual string message(int ev) const`:
  This member returns a string describing the error condition denoted by `ev`, which should be a (cast to `int`) value of the category's error condition enumeration;

- `virtual char const *name() const noexcept`:
  This member returns the name of the error category as NTBS (like `generic`);

- `bool operator<(error_category const &rhs) const noexcept`:
  returns `less<const error_category*>()(this, &rhs)`.

- Error category objects can be compared for (in)equality.

The functions returning predefined error categories are:

- `error_category const &generic_category() noexcept`:
  returns a reference to the generic `error_category` object. The returned object's `name` member returns a pointer to the string `"generic"`;

- `error_category const &system_category() noexcept`:
  returns a reference to the operating system `error_category` object: it is used for errors reported by the operating system. The object's `name` member returns a pointer to the string `"system"`;

- `error_category const &iostream_category() noexcept`:
  returns a reference to the iostream `error_category` object: it is used for errors reported by stream objects. The object's `name` member returns a pointer to the string `"iostream"`;

- `error_category const &future_category() noexcept`:
  returns a reference to the future `error_category` object: it is used for errors reported by `future' objects (cf. section 20.8). The object's `name` member returns a pointer to the string `"future"`;

### 10.9.2: The class `std::error_condition'

`Error_condition` objects contain information about `higher level' types of errors. They are supposed to be platform independent like syntax errors or non-existing requests.

Error condition objects are returned by the member `default_error_condition` of the classes `error_code` and `error_category`, and they are returned by the function `std::error_condition make_error_condition(ErrorConditionEnum ec)`. The type name `ErrorConditionEnum` is a formal name for an `enum class` that enumerates the `higher level' error types. The `error_condition` objects returned by `make_error_condition` are initialized with `ec` and the `error_category` that uses the `ErrorConditionEnum`. Defining your own `ErrorConditionEnum` is covered in section 23.7.

Constructors:

- `error_condition() noexcept`:
  the object's value is initialized to `no error' (i.e., 0) and a `system_category` error category;

- The copy constructor is available;

- `error_condition(int ec, error_category const &cat) noexcept`:
  the object's value is initialized to `ec` and error category `cat`. It is the responsibility of the caller to ensure that `ec` represents a (cast to `int`) value of `cat's` error condition enumeration;

- `error_condition(ErrorConditionEnum value) noexcept`:
  this is a member template (cf. section 22.1.3), using template header `template <class ErrorConditionEnum>`. It initializes the object with the return value of `make_error_condition(value)`;

Members:

- The copy assignment operator and an assignment operator accepting an `ErrorConditionEnum` are available;

- `void assign(int val, error_category const &cat)`:
  assigns new values to the current object's value and category data members;

- `error_category const &category() const noexcept`:
  returns a reference to the object's error category (note that this is a reference to the category's singleton object);

- `void clear() noexcept`:
  after calling this member value is set to 0 and the object's error category set to `generic_category`;

- `string message() const`:
  returns `category().message(value())`;

- `explicit operator bool() const noexcept`:
  returns `true` if `value()` returns a non-zero value (so its semantic meaning is `the object represents an error');

- `int value() const noexcept`:
  returns the object's error value.

Two `error_condition` objects can be compared for (in)equality, and can be ordered using `operator<`. Ordering is pointless if the two objects refer to different error categories. If the categories of two objects are different they are considered different.

### 10.9.3: The class system_error

`System_error` objects can be constructed from `error_codes` or from error values (`ints`) and matching error category objects, optionally followed by a standard textual description of the nature of the encountered error.

Here is the class's public interface:

       class system_error: public runtime_error
        {
            public:
                system_error(error_code ec);
                system_error(error_code ec, string const &what_arg);
                system_error(error_code ec, char const *what_arg);

                system_error(int ev, error_category const &ecat);
                system_error(int ev, error_category const &ecat,
                                 char const *what_arg);
                system_error(int ev, error_category const &ecat,
                                 string const &what_arg);

                error_code const &code() const noexcept;
                char const *what() const noexcept;
        }

The `ev` values often are the values of the `errno` variable as set upon failure by system level functions like chmod(2).

Note that the first three constructors shown in the interface receive an `error_code` object as their first arguments. As one of the `error_code` constructors also expects an `int` and and `error_category` argument, the second set of three constructors could also be used instead of the first set of three constructors. E.g.,

        system_error(errno, system_category(), "context of the error");
        // identical to:
        system_error(error_code(errno, system_category()),
                                                "context of the error");

The second set of three constructors are primarily used when an existing function already returns an `error_code`. E.g.,

        system_error(make_error_code(errc::bad_address),
                                                "context of the error");
        // or maybe:
        system_error(make_error_code(static_cast<errc>(errno)),
                                                "context of the error");

In addition to the standard `what` member, the `system_error` class also offers a member `code` returning a const reference to the exception's error code.

The NTBS returned by `system_error's what` member may be formatted by a `system_error` object:

        what_arg + ": " + code().message()

Note that, although `system_error` was derived from `runtime_error`, you'll lose the `code` member when catching a `std::exception` object. Of course, downcasting is possible, but that's a stopgap. Therefore, if a `system_error` is thrown, a matching `catch (system_error const &)` clause must be provided to retrieve the value returned by the `code` member. This, and the rather complex organization of the classes that are involved when using `system_error` result in a very complex, and hard to generalize exception handling. In essence, what you obtain at the cost of high complexity is a facility for categorizing `int` or `enum` error values. Additional coverage of the involved complexities is provided in chapter 23, in particular section 23.7 (for a flexible alternative, see the class `FBB::Exception` in the author's Bobcat library).

### 10.9.4: Exception propagation: std::exception_ptr

In practice almost everything can be used as an exception. But at the same time any exception that is thrown can be reached using the function (`std::current_exception`), and access to any exception can be standardized using `std::make_exception_ptr`. These functions expect or use objects of the class `std::exception_ptr`, and in this section we take a closer look at tha class.

The class `exception_ptr's` default constructor initializes it to a null-pointer. In the following code snippet the variable `isNull` is set to true:

        std::exception_ptr obj;
        bool isNull =  obj == nullptr && obj == 0;

The class `exception_ptr` provides copy and move constructors as well as copy and move assignment operators.

Two `exception_ptr` objects can be compared for equality. They are equal if they refer to the same exception. Move assignment transfers the exception referred to by the right-hand side operand to the left-hand side operand, and turns the right-hand side operand into a null pointer.

There is no published method directly retrieving the exception to which an `exception_ptr` object refers. However, there are some free functions constructing or handling `exception_ptr` objects:

- `std::exception_ptr std::current_exception() noexcept`:
  An `exception_ptr` object is returned referring to the currently handled exception (or a copy of the currently handled exception, or a default constructed `exception_ptr` object if no current exception is available). This function can also be called when a default exception catcher is used.

  The exception referred to by `current_exception` does not have to be an object of the class `std::exception`. Any type of object or value thrown as an exception is retrieved as an `exception_ptr` by `current_exception`. The exception referred to by an `exception_ptr` object remains valid for at least as long as there exists an `exception_ptr` object that refers to it. Calling `current_exception` twice in a row then the two returned `exception_ptr` objects may or may not refer to the same exception object.

- `std::exception_ptr make_exception_ptr(Type value) noexcept`:
  This function template constructs an `exception_ptr` from a value of any type which is passed as its argument. `Type` does not necessarily have to be a `std::exception` but can be anything that can be thrown as an exception: an `int`, a `std::string`, a `std::exception`, you name it.

  Here are some examples, showing how values of different types can be passed as arguments to `make_exception_ptr`

          auto ptr = make_exception_ptr(exception());
          ptr = make_exception("hello world"s);
          ptr = make_exception(12);

- `void std::rethrow_exception(exception_ptr obj)`:
  The exception to which `obj` refers is thrown. Note: `obj` cannot be a `nullptr`.

## 10.10: Exception guarantees

Software should be exception safe: the program should continue to work according to its specifications in the face of exceptions. It is not always easy to realize exception safety. In this section some guidelines and terminology is introduced when discussing exception safety.

Since exceptions may be generated from within all C++ functions, exceptions may be generated in many situations. Not all of these situations are immediately and intuitively recognized as situations where exceptions can be thrown. Consider the following function and ask yourself at which points exceptions may be thrown:

        void fun()
        {
            X x;
            cout << x;
            X *xp = new X{ x };
            cout << (x + *xp);
            delete xp;
        }

If it can be assumed that `cout` as used above does not throw an exception there are at least 13 opportunities for exceptions to be thrown:

- `X x`: the default constructor could throw an exception (#1)
- `cout << x`: the overloaded insertion operator could throw an exception (#2), but its rhs argument might not be an `X` but, e.g., an `int`, and so `X::operator int() const` could be called which offers yet another opportunity for an exception (#3).
- `*xp = new X{ x }`: the copy constructor may throw an exception (#4) and operator new (#5a) too. But did you realize that this latter exception might not be thrown from `::new`, but from, e.g., `X`'s own overload of `operator new`? (#5b)
- `cout << (x + *xp)`: we might be seduced into thinking that two `X` objects are added. But it doesn't have to be that way. A separate class Y might exist and `X` may have a conversion operator `operator Y() const`, and `operator+(Y const &lhs, X const &rhs), operator+(X const &lhs, Y const &rhs)`, and `operator+(X const &lhs, X const &rhs)` might all exist. So, if the conversion operator exists, then depending on the kind of overload of `operator+` that is defined either the addition's left-hand side operand (#6), right-hand side operand (#7), or `operator+` itself (#8) may throw an exception. The resulting value may again be of any type and so the overloaded `cout << return-type-of-operator+` operator may throw an exception (#9). Since `operator+` returns a temporary object it is destroyed shortly after its use. `X`'s destructor could throw an exception (#10).
- `delete xp`: whenever `operator new` is overloaded `operator delete` should be overloaded as well and may throw an exception (#11). And of course, `X`'s destructor might again throw an exception (#12).
- `}`: when the function terminates the local `x` object is destroyed: again an exception could be thrown (#13).

It is stressed here (and further discussed in section 10.12) that although it is possible for exceptions to leave destructors this would violate the C++ standard and so it must be prevented in well-behaving C++ programs.

How can we expect to create working programs when exceptions might be thrown in so many situations?

Exceptions may be generated in a great many situations, but serious problems are prevented when we're able to provide at least one of the following exception guarantees:

- The basic guarantee: no resources are leaked. In practice this means: all allocated memory is properly returned when exceptions are thrown.
- The strong guarantee: the program's state remains unaltered when an exception is thrown (as an example: the canonical form of the overloaded assignment operator provides this guarantee)
- The nothrow guarantee: this applies to code for which it can be proven that no exception can be thrown from it.

### 10.10.1: The basic guarantee

The basic guarantee dictates that functions that fail to complete their assigned tasks must return all allocated resources, usually memory, before terminating. Since practically all functions and operators may throw exceptions and since a function may repeatedly allocate resources the blueprint of a function allocating resources shown below defines a try block to catch all exceptions that might be thrown. The catch handler's task is to return all allocated resources and then rethrow the exception.

        void allocator(X **xDest, Y **yDest)
        {
            X *xp = 0;              // non-throwing preamble
            Y *yp = 0;

            try                     // this part might throw
            {
                xp = new X[nX];     // alternatively: allocate one object
                yp = new Y[nY];
            }
            catch (...)
            {
                delete xp;
                throw;
            }

            delete[] *xDest;        // non-throwing postamble
            *xDest = xp;
            delete[] *yDest;
            *yDest = yp;
        }

In the pre-try code the pointers to receive the addresses returned by the operator `new` calls are initialized to 0. Since the catch handler must be able to return allocated memory they must be available outside of the `try` block. If the allocation succeeds the memory pointed to by the destination pointers is returned and then the pointers are given new values.

Allocation and or initialization might fail. If allocation fails `new` throws a `std::bad_alloc` exception and the catch handler simply deletes 0-pointers which is OK.

If allocation succeeds but the construction of (some) of the objects fails by throwing an exception then the following is guaranteed to happen:

- The destructors of all successfully allocated objects are called;
- The dynamically allocated memory to contain the objects is returned

Consequently, there is no memory leak when `new` fails. Inside the above `try` block `new X` may fail: this does not affect the 0-pointers and so the catch handler merely deletes 0 pointers. When `new Y` fails `xp` points to allocated memory and so it must be returned. This happens inside the catch handler. The final pointer (here: `yp`) will only be unequal zero when `new Y` properly completes, so there's no need for the catch handler to return the memory pointed at by `yp`.

### 10.10.2: The strong guarantee

The strong guarantee dictates that an object's state should not change in the face of exceptions. This is realized by performing all operations that might throw on a separate copy of the data. If all this succeeds then the current object and its (now successfully modified) copy are swapped. An example of this approach can be observed in the canonical overloaded assignment operator:

        Class &operator=(Class const &other)
        {
            Class tmp(other);
            swap(tmp);
            return *this;
        }

The copy construction might throw an exception, but this keeps the current object's state intact. If the copy construction succeeds `swap` swaps the current object's content with `tmp`'s content and returns a reference to the current object. For this to succeed it must be guaranteed that `swap` won't throw an exception. Returning a reference (or a value of a primitive data type) is also guaranteed not to throw exceptions. The canonical form of the overloaded assignment operator therefore meets the requirements of the strong guarantee.

Some rules of thumb were formulated that relate to the strong guarantee (cf. Sutter, H., Exceptional C++, Addison-Wesley, 2000). E.g.,

- All the code that might throw an exception affecting the current state of an object should perform its tasks separately from the data controlled by the object. Once this code has performed its tasks without throwing an exception replace the object's data by the new data.
- Member functions modifying their object's data should not return original (contained) objects by value.

The canonical assignment operator is a good example of the first rule of thumb. Another example is found in classes storing objects. Consider a class `PersonDb` storing multiple `Person` objects. Such a class might offer a member `void add(Person const &next)`. A plain implementation of this function (merely intended to show the application of the first rule of thumb, but otherwise completely disregarding efficiency considerations) might be:

        Person *PersonDb::newAppend(Person const &next)
        {
            Person *tmp = 0;
            try
            {
                tmp = new Person[d_size + 1];
                for (size_t idx = 0; idx < d_size; ++idx)
                    tmp[idx] = d_data[idx];
                tmp[d_size] = next;
                return tmp;
            }
            catch (...)
            {
                delete[] tmp;
                throw;
            }
        }

        void PersonDb::add(Person const &next)
        {
            Person *tmp = newAppend(next);
            delete[] d_data;
            d_data = tmp;
            ++d_size;
        }

The (private) `newAppend` member's task is to create a copy of the currently allocated `Person` objects, including the data of the next `Person` object. Its `catch` handler catches any exception that might be thrown during the allocation or copy process and returns all memory allocated so far, rethrowing the exception at the end. The function is exception neutral as it propagates all its exceptions to its caller. The function also doesn't modify the `PersonDb` object's data, so it meets the strong exception guarantee. Returning from `newAppend` the member `add` may now modify its data. Its existing data are returned and its `d_data` pointer is made to point to the newly created array of `Person` objects. Finally its `d_size` is incremented. As these three steps don't throw exceptions `add` too meets the strong guarantee.

The second rule of thumb (member functions modifying their object's data should not return original (contained) objects by value) may be illustrated using a member `PersonDb::erase(size_t idx)`. Here is an implementation attempting to return the original `d_data[idx]` object:

        Person PersonData::erase(size_t idx)
        {
            if (idx >= d_size)
                throw "Array bounds exceeded"s;
            Person ret(d_data[idx]);
            Person *tmp = copyAllBut(idx);
            delete[] d_data;
            d_data = tmp;
            --d_size;
            return ret;
        }

Although copy elision usually prevents the use of the copy constructor when returning `ret`, this is not guaranteed to happen. Furthermore, a copy constructor may throw an exception. If that happens the function has irrevocably mutated the `PersonDb`'s data, thus losing the strong guarantee.

Rather than returning `d_data[idx]` by value it might be assigned to an external `Person` object before mutating `PersonDb`'s data:

        void PersonData::erase(Person *dest, size_t idx)
        {
            if (idx >= d_size)
                throw "Array bounds exceeded"s;
            *dest = d_data[idx];
            Person *tmp = copyAllBut(idx);
            delete[] d_data;
            d_data = tmp;
            --d_size;
        }

This modification works, but changes the original assignment of creating a member returning the original object. However, both functions suffer from a task overload as they modify `PersonDb`'s data and also return an original object. In situations like these the one-function-one-responsibility rule of thumb should be kept in mind: a function should have a single, well defined responsibility.

The preferred approach is to retrieve `PersonDb`'s objects using a member like `Person const &at(size_t idx) const` and to erase an object using a member like `void PersonData::erase(size_t idx)`.

### 10.10.3: The nothrow guarantee

Exception safety can only be realized if some functions and operations are guaranteed not to throw exceptions. This is called the nothrow guarantee. An example of a function that must offer the nothrow guarantee is the `swap` function. Consider once again the canonical overloaded assignment operator:

        Class &operator=(Class const &other)
        {
            Class tmp(other);
            swap(tmp);
            return *this;
        }

If `swap` were allowed to throw exceptions then it would most likely leave the current object in a partially swapped state. As a result the current object's state would most likely have been changed. As `tmp` has been destroyed by the time a catch handler receives the thrown exception it becomes very difficult (as in: impossible) to retrieve the object's original state. Losing the strong guarantee as a consequence.

The `swap` function must therefore offer the nothrow guarantee. It must have been designed as if using the following prototype (see also section 23.8):

        void Class::swap(Class &other) noexcept;

Likewise, `operator delete` and `operator delete[]` offer the nothrow guarantee, and according to the C++ standard destructors may themselves not throw exceptions (if they do their behavior is formally undefined, see also section 10.12 below).

Since the C programming language does not define the exception concept functions from the standard C library offer the nothrow guarantee by implication. This allowed us to define the generic `swap` function in section 9.6 using `memcpy`.

Operations on primitive types offer the nothrow guarantee. Pointers may be reassigned, references may be returned etc. etc. without having to worry about exceptions that might be thrown.

## 10.11: Function try blocks

Exceptions may be generated from inside constructors. How can exceptions generated in such situations be caught by the constructor itself, rather than outside the constructor? The intuitive solution, nesting the object construction in a `try` block does not solve the problem. The exception by then has left the constructor and the object we intended to construct isn't visible anymore.

Using a nested `try` block is illustrated in the next example, where `main` defines an object of class `PersonDb`. Assuming that `PersonDb`'s constructor throws an exception, there is no way we can access the resources that might have been allocated by `PersonDb`'s constructor from the catch handler as the `pdb` object is out of scope:

        int main(int argc, char **argv)
        {
            try
            {
                PersonDb pdb{ argc, argv }; // may throw exceptions
                ...                         // main()'s other code
            }
            catch (...)                      // and/or other handlers
            {
                ...                         // pdb is inaccessible from here
            }
        }

Although all objects and variables defined inside a `try` block are inaccessible from its associated catch handlers, object data members were available before starting the `try` block and so they may be accessed from a catch handler. In the following example the catch handler in `PersonDb`'s constructor is able to access its `d_data` member:

        PersonDb::PersonDb(int argc, char **argv)
        :
            d_data(0),
            d_size(0)
        {
            try
            {
                initialize(argc, argv);
            }
            catch (...)
            {
                // d_data, d_size: accessible
            }
        }

Unfortunately, this does not help us much. The `initialize` member is unable to reassign `d_data` and `d_size` if `PersonDb const pdb` was defined; the `initialize` member should at least offer the basic exception guarantee and return any resources it has acquired before terminating due to a thrown exception; and although `d_data` and `d_size` offer the nothrow guarantee as they are of primitive data types a class type data member might throw an exception, possibly resulting in violation of the basic guarantee.

In the next implementation of `PersonDb` assume that constructor receives a pointer to an already allocated block of `Person` objects. The `PersonDb` object takes ownership of the allocated memory and it is therefore responsible for the allocated memory's eventual destruction. Moreover, `d_data` and `d_size` are also used by a composed object `PersonDbSupport`, having a constructor expecting a `Person const *` and `size_t` argument. Our next implementation may then look something like this:

        PersonDb::PersonDb(Person *pData, size_t size)
        :
            d_data(pData),
            d_size(size),
            d_support(d_data, d_size)
        {
            // no further actions
        }

This setup allows us to define a `PersonDb const &pdb`. Unfortunately, `PersonDb` cannot offer the basic guarantee. If `PersonDbSupport`'s constructor throws an exception it isn't caught although `d_data` already points to allocated memory.

The function try block offers a solution for this problem. A function try block consists of a `try` block and its associated handlers. The function `try` block starts immediately after the function header, and its block defines the function body. With constructors base class and data member initializers may be placed between the `try` keyword and the opening curly brace. Here is our final implementation of `PersonDb`, now offering the basic guarantee:

        PersonDb::PersonDb(Person *pData, size_t size)
        try
        :
            d_data(pData),
            d_size(size),
            d_support(d_data, d_size)
        {}
        catch (...)
        {
            delete[] d_data;
        }

Let's have a look at a stripped-down example. A constructor defines a function try block. The exception thrown by the `Throw` object is initially caught by the object itself. Then it is rethrown. The surrounding `Composer`'s constructor also defines a function try block, `Throw`'s rethrown exception is properly caught by `Composer`'s exception handler, even though the exception was generated from within its member initializer list:

        #include <iostream>

        class Throw
        {
            public:
                Throw(int value)
                try
                {
                    throw value;
                }
                catch (...)
                {
                    std::cout << "Throw's exception handled locally by Throw()\n";
                    throw;
                }
        };

        class Composer
        {
            Throw d_t;
            public:
                Composer()
                try             // NOTE: try precedes initializer list
                :
                    d_t(5)
                {}
                catch (...)
                {
                    std::cout << "Composer() caught exception as well\n";
                }
        };

        int main()
        {
            Composer c;
        }

When running this example, we're in for a nasty surprise: the program runs and then breaks with an abort exception. Here is the output it produces, the last two lines being added by the system's final catch-all handler, catching all remaining uncaught exceptions:

        Throw's exception handled locally by Throw()
        Composer() caught exception as well
        terminate called after throwing an instance of 'int'
        Abort

The reason for this is documented in the C++ standard: at the end of a catch-handler belonging to a constructor or destructor function try block, the original exception is automatically rethrown.

The exception is not rethrown if the handler itself throws another exception, offering the constructor or destructor a way to replace a thrown exception by another one. The exception is only rethrown if it reaches the end of the catch handler of a constructor or destructor function try block. Exceptions caught by nested catch handlers are not automatically rethrown.

As only constructors and destructors rethrow exceptions caught by their function try block catch handlers the run-time error encountered in the above example may simply be repaired by providing `main` with its own function try block:

        int main()
        try
        {
            Composer c;
        }
        catch (...)
        {}

Now the program runs as planned, producing the following output:

        Throw's exception handled locally by Throw()
        Composer() caught exception as well

A final note: if a function defining a function try block also declares an exception throw list then only the types of rethrown exceptions must match the types mentioned in the throw list.

## 10.12: Exceptions in constructors

Object destructors are only activated for completely constructed objects. Although this may sound like a truism, there is a subtlety here. If the construction of an object fails for some reason, the object's destructor is not called when the object goes out of scope. This could happen if an exception that is generated by the constructor is not caught by the constructor. If the exception is thrown when the object has already allocated some memory, then that memory is not returned: its destructor isn't called as the object's construction wasn't successfully completed.

The following example illustrates this situation in its prototypical form. The constructor of the class `Incomplete` first displays a message and then throws an exception. Its destructor also displays a message:

        class Incomplete
        {
            public:
                Incomplete()
                {
                    cerr << "Allocated some memory\n";
                    throw 0;
                }
                ~Incomplete()
                {
                    cerr << "Destroying the allocated memory\n";
                }
        };

Next, `main()` creates an `Incomplete` object inside a `try` block. Any exception that may be generated is subsequently caught:

        int main()
        {
            try
            {
                cerr << "Creating `Incomplete' object\n";
                Incomplete{};
                cerr << "Object constructed\n";
            }
            catch (...)
            {
                cerr << "Caught exception\n";
            }
        }

When this program is run, it produces the following output:

        Creating `Incomplete' object
        Allocated some memory
        Caught exception

Thus, if `Incomplete`'s constructor would actually have allocated some memory, the program would suffer from a memory leak. To prevent this from happening, the following counter measures are available:

- Prevent the exceptions from leaving the constructor.
  If part of the constructor's body may generate exceptions, then this part may be surrounded by a `try` block, allowing the exception to be caught by the constructor itself. This approach is defensible when the constructor is able to repair the cause of the exception and to complete its construction as a valid object.
- If an exception is generated by a base class constructor or by a member initializing constructor then a `try` block within the constructor's body won't be able to catch the thrown exception. This always results in the exception leaving the constructor and the object is not considered to have been properly constructed. A `try` block may include the member initializers, and the `try` block's compound statement becomes the constructor's body as in the following example:

      class Incomplete2
      {
          Composed d_composed;
          public:
              Incomplete2()
              try
              :
                  d_composed(/* arguments */)
              {
                  // body
              }
              catch (...)
              {}
      };

  An exception thrown by either the member initializers or the body results in the execution never reaching the body's closing curly brace. Instead the catch clause is reached. Since the constructor's body isn't properly completed the object is not considered properly constructed and eventually the object's destructor won't be called.

The catch clause of a constructor's function `try` block behaves slightly different than a catch clause of an ordinary function `try` block. An exception reaching a constructor's function `try` block may be transformed into another exception (which is thrown from the catch clause) but if no exception is explicitly thrown from the catch clause the exception originally reaching the catch clause is always rethrown. Consequently, there's no way to confine an exception thrown from a base class constructor or from a member initializer to the constructor: such an exception always propagates to a more shallow block and in that case the object's construction is always considered incomplete.

Therefore, if incompletely constructed objects throw exceptions then the constructor remains responsible for preventing memory (generally: resource) leaks. There are several ways to realize this:

- If the constructor defines a function try block, then the constructor's catch clause cannot use any of its data members anymore. By implication: if the constructor has allocated memory pointed to by one of its data members, then the catch-clause cannot delete that memory. Instead, the constructor's body itself must ensure that the memory is properly deleted;
- When multiple inheritance is used: if initial base classes have properly been constructed and a later base class throws, then the initial base class objects are automatically destroyed (as they are themselves fully constructed objects)
- When composition is used: already constructed composed objects are automatically destroyed (as they are fully constructed objects)
- Instead of using plain pointers smart pointers (cf. section 18.4) should be used to manage dynamically allocated memory. In this case, if the constructor throws either before or after the allocation of the dynamic memory, then allocated memory is properly returned as `shared_ptr` objects are, after all, objects.
- If plain pointer data members must be used then the constructor's body should first, in its member initialization section, initialize its plain pointer data members. Then, in its body it can dynamically allocate memory, reassigning the plain pointer data members. In these cases the pointer-handling must be embedded in a try-block, allowing the constructor to free the allocated memory before a final exception is thrown, possibly reaching the catch clause of the constructor's function try block. That final catch clause can complete whatever actions are required (e.g., write a log-file entry). Example:

      class Incomplete2
      {
          Composed d_composed;
          char *d_cp;         // plain pointers
          int *d_ip;

          public:
              Incomplete2(size_t nChars, size_t nInts)
              try
              :
                  d_composed(/* arguments */),    // might throw
                  d_cp(0),
                  d_ip(0)
              {
                  try
                  {
                      preamble();                     // might throw
                      d_cp = new char[nChars];        // might throw
                      d_ip = new int[nChars];         // might throw
                      postamble();                    // might throw
                  }
                  catch (...)
                  {
                      delete[] d_cp;                  // clean up
                      delete[] d_ip;
                      throw;                          // retrow the exception
                  }
              }
              catch (...)
              {
                  // maybe write a log-entry, but also throws
                  // the original exception
              }
      };

On the other hand, C++ supports constructor delegation, so an object may have been completely constructed according to the C++ run-time system, but yet its (delegating) constructor may throw an exception, as illustrated by the next example:

         1: #include <iostream>
         2: using namespace std;
         3:
         4: class Delegate
         5: {
         6:     char *d_p1;
         7:     char *d_p2;
         8:
         9:     public:
        10:         Delegate()      // succeeds -> object constructed
        11:         :
        12:             Delegate(0)
        13:         {
        14:             d_p2 = new char[10];
        15:             cout << "default, throws...\n";
        16:             throw 12;   // but considered constructed
        17:         }
        18:         ~Delegate()
        19:         {
        20:             delete[] d_p1;
        21:             delete[] d_p2;
        22:             cout << "destructor\n";
        23:         }
        24:
        25:     private:
        26:         Delegate(int x)         // completes OK
        27:         :
        28:             d_p1(0),
        29:             d_p2(0)
        30:         {
        31:             cout << "delegated\n";
        32:         }
        33: };
        34:
        35: int main()
        36: try
        37: {
        38:     Delegate del;           // throws
        39:
        40:     cout << "never reached\n";
        41: } // del's destructor is called here
        42: catch (...)
        43: {
        44:     cout << "main's catch clause\n";
        45: }

Here it is the responsibility of `Delegate`'s designer to ensure that the throwing default constructor does not invalidate the actions performed by the `Delegate(int x)` constructor. The latter constructor is called (line 12) by the default constructor, and merely initializes (lines 28, 29) the data members at lines 6 and 7. Next, the default constructor, after allocating some memory, throws an exception (line 16). In fact, an exception may be called at any point, since the destructor (line 18) will be called automatically anyway (line 41). If multiple exceptions could be thrown then `Delegate` can define an enumeration and a data member of that enumeration type, which is set to the enum value indication the nature of the next exception (if it is thrown), so the destructor can handle the exception according to its type.

## 10.13: Exceptions in destructors

According to the C++ standard exceptions thrown by destructors may not leave their bodies. Providing a destructor with a function `try` block is therefore a violation of the standard: exceptions caught by a function `try` block's catch clause have already left the destructor's body. If --in violation of the standard-- the destructor is provided with a function `try` block and an exception is caught by the `try` block then that exception is rethrown, similar to what happens in catch clauses of constructor functions' `try` blocks.

The consequences of an exception leaving the destructor's body is not defined, and may result in unexpected behavior. Consider the following example:

Assume a carpenter builds a cupboard having a single drawer. The cupboard is finished, and a customer, buying the cupboard, finds that the cupboard can be used as expected. Satisfied with the cupboard, the customer asks the carpenter to build another cupboard, this time having two drawers. When the second cupboard is finished, the customer takes it home and is utterly amazed when the second cupboard completely collapses immediately after it is used for the first time.

Weird story? Then consider the following program:

        int main()
        {
            try
            {
                cerr << "Creating Cupboard1\n";
                Cupboard1{};
                cerr << "Beyond Cupboard1 object\n";
            }
            catch (...)
            {
                cerr << "Cupboard1 behaves as expected\n";
            }
            try
            {
                cerr << "Creating Cupboard2\n";
                Cupboard2{};
                cerr << "Beyond Cupboard2 object\n";
            }
            catch (...)
            {
                cerr << "Cupboard2 behaves as expected\n";
            }
        }

When this program is run it produces the following output:

        Creating Cupboard1
        Drawer 1 used
        Cupboard1 behaves as expected
        Creating Cupboard2
        Drawer 2 used
        Drawer 1 used
        terminate called after throwing an instance of 'int'
        Abort

The final `Abort` indicates that the program has aborted instead of displaying a message like `Cupboard2 behaves as expected`.

Let's have a look at the three classes involved. The class `Drawer` has no particular characteristics, except that its destructor throws an exception:

        class Drawer
        {
            size_t d_nr;
            public:
                Drawer(size_t nr)
                :
                    d_nr(nr)
                {}
                ~Drawer()
                {
                    cerr << "Drawer " << d_nr << " used\n";
                    throw 0;
                }
        };

The class `Cupboard1` has no special characteristics at all. It merely has a single composed `Drawer` object:

        class Cupboard1
        {
            Drawer left;
            public:
                Cupboard1()
                :
                    left(1)
                {}
        };

The class `Cupboard2` is constructed comparably, but it has two composed `Drawer` objects:

        class Cupboard2
        {
            Drawer left;
            Drawer right;
            public:
                Cupboard2()
                :
                    left(1),
                    right(2)
                {}
        };

When `Cupboard1`'s destructor is called `Drawer`'s destructor is eventually called to destroy its composed object. This destructor throws an exception, which is caught beyond the program's first `try` block. This behavior is completely as expected.

A subtlety here is that `Cupboard1`'s destructor (and hence `Drawer`'s destructor) is activated immediately subsequent to its construction. Its destructor is called immediately subsequent to its construction as `Cupboard1()` defines an anonymous object. As a result the `Beyond Cupboard1 object` text is never inserted into `std::cerr`.

Because of `Drawer`'s destructor throwing an exception a problem occurs when `Cupboard2`'s destructor is called. Of its two composed objects, the second `Drawer`'s destructor is called first. This destructor throws an exception, which ought to be caught beyond the program's second `try` block. However, although the flow of control by then has left the context of `Cupboard2`'s destructor, that object hasn't completely been destroyed yet as the destructor of its other (left) `Drawer` still has to be called.

Normally that would not be a big problem: once an exception is thrown from `Cupboard2`'s destructor any remaining actions would simply be ignored, albeit that (as both drawers are properly constructed objects) `left`'s destructor would still have to be called.

This happens here too and `left`'s destructor also needs to throw an exception. But as we've already left the context of the second `try` block, the current flow control is now thoroughly mixed up, and the program has no other option but to abort. It does so by calling `terminate()`, which in turn calls `abort()`. Here we have our collapsing cupboard having two drawers, even though the cupboard having one drawer behaves perfectly.

The program aborts since there are multiple composed objects whose destructors throw exceptions leaving the destructors. In this situation one of the composed objects would throw an exception by the time the program's flow control has already left its proper context causing the program to abort.

The C++ standard therefore understandably stipulates that exceptions may never leave destructors. Here is the skeleton of a destructor whose code might throw exceptions. No function `try` block but all the destructor's actions are encapsulated in a `try` block nested under the destructor's body.

        Class::~Class()
        {
            try
            {
                maybe_throw_exceptions();
            }
            catch (...)
            {}
        }

- Table of Contents
- Previous Chapter
- Next Chapter