Contributor's Corner

A collection of hopefully helpful information
Functionality Clarity Elegance

  C++ Exceptions   

Concepts & Techniques

Rule Three:
Practice exception safety

Exception safety amounts to coding your program in ways to provide certain guarantees of behaviour when an exception occurs. It is useful to design operations in terms of the guarantees they provide if an exception is thrown. The guarantees that are provided by operations in the standard library are;
  1. The strong guarantee means that an operation succeeds or, if it fails, has no effect.
  2. The basic guarantee means that the object remains in a valid state, can be destructed, and no resources are leaked.
  3. The nothrow guarantee means that an operation is guaranteed to never throw exceptions, as well as not introducing resource leaks or leaving the object in an invalid state. In other words, if an exception is thrown within a function, it is recovered from and the exception is not propagated.
An example where the strong guarantee would be needed is in banking. A transaction on a savings account should either succeed or, if it fails, have no effect. An unauthorised withdrawal should not occur, and not change the account balance. The basic guarantee is a bit weaker. If an error occurs, the object can be successfully reassigned or destroyed, but it's contents may be unpredictable. These guarantees come at different cost. The strong guarantee is the most expensive, as it can mean backtracking to a previous known state when an error occurs. The basic guarantee is the minimum that one should aim for, as it is otherwise not possible to use the object again. All operations in the standard library provide one of the above guarantees, subject to user-defined objects also providing similar guarantees. For example, std::vector::push_back() [used to add an element to the end of a vector] always provides the strong guarantee. However, all variants of std::vector::insert() [used to insert elements into the middle of a vector] only provide the strong guarantee if the copy constructor of X provides the nothrow guarantee. Multi-element insertions into a std::map only provides the basic guarantee. The tools that we, the humble programmer, have to provide these guarantees are;
  1. the try/catch block. For example, one way of implementing a nothrow guarantee is to catch an exception, recover from it, and not throw anything again;
  2. the RAII technique mentioned above;
  3. never let go of a piece of information until we can store its replacement without triggering an exception; and
  4. ensure all objects are in a valid state before throwing an exception;
  5. ensure all resources that may need to be released are owned by an object (so that object's destructor will release the resource) or release any unowned resources immediately before throwing an exception.

 Concepts & Techniques: Rule TwoExamples