Termination
Prev | Chapter 4. Support | Next

## Termination

### Termination Handlers

Not many changes here to `cstdlib`. You should note that the `abort()` function does not call the destructors of automatic nor static objects, so if you're depending on those to do cleanup, it isn't going to happen. (The functions registered with `atexit()` don't get called either, so you can forget about that possibility, too.)

The good old `exit()` function can be a bit funky, too, until you look closer. Basically, three points to remember are:

1. Static objects are destroyed in reverse order of their creation.

2. Functions registered with `atexit()` are called in reverse order of registration, once per registration call. (This isn't actually new.)

3. The previous two actions are “interleaved,” that is, given this pseudocode:

         extern "C or C++" void  f1 (void);
         extern "C or C++" void  f2 (void);

         static Thing obj1;
         atexit(f1);
         static Thing obj2;
         atexit(f2);

   then at a call of `exit()`, `f2` will be called, then `obj2` will be destroyed, then `f1` will be called, and finally `obj1` will be destroyed. If `f1` or `f2` allow an exception to propagate out of them, Bad Things happen.

Note also that `atexit()` is only required to store 32 functions, and the compiler/library might already be using some of those slots. If you think you may run out, we recommend using the `xatexit`/`xexit` combination from `libiberty`, which has no such limit.

### Verbose Terminate Handler

If you are having difficulty with uncaught exceptions and want a little bit of help debugging the causes of the core dumps, you can make use of a GNU extension, the verbose terminate handler.

    #include <exception>

    int main()
    {
      std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
      ...

      throw anything;
    }

The `__verbose_terminate_handler` function obtains the name of the current exception, attempts to demangle it, and prints it to stderr. If the exception is derived from `exception` then the output from `what()` will be included.

Any replacement termination function is required to kill the program without returning; this one calls abort.

For example:

    #include <exception>
    #include <stdexcept>

    struct argument_error : public std::runtime_error
    {
      argument_error(const std::string& s): std::runtime_error(s) { }
    };

    int main(int argc)
    {
      std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
      if (argc > 5)
        throw argument_error("argc is greater than 5!");
      else
        throw argc;
    }

With the verbose terminate handler active, this gives:

       % ./a.out
       terminate called after throwing a `int'
       Aborted
       % ./a.out f f f f f f f f f f f
       terminate called after throwing an instance of `argument_error'
       what(): argc is greater than 5!
       Aborted

The 'Aborted' line comes from the call to `abort()`, of course.

This is the default termination handler; nothing need be done to use it. To go back to the previous “silent death” method, simply include `exception` and `cstdlib`, and call

         std::set_terminate(std::abort);

After this, all calls to `terminate` will use `abort` as the terminate handler.

Note: the verbose terminate handler will attempt to write to stderr. If your application closes stderr or redirects it to an inappropriate location, `__verbose_terminate_handler` will behave in an unspecified manner.

Prev | Up | Next
Dynamic Memory | Home | Chapter 5. Diagnostics