Session 11: When things go wrong: Exceptions and Resource management

Outline

Failures (revision)

Throwing an exception in C++

Catching an exception in C++

C++ has a try/catch statement, largely copied by Java:

        try {
                // do something that might fail
        } catch (MyException &e) {
                // deal with the exception
        } catch (AnotherException) {
                // deal with the exception
        }
Exceptions may be organized into hierarchies, as in Java, and a catch clause also handles any derived class.

The C++ treatment of exceptions

This is called unwinding the stack.

Clean up and rethrow

Often exception handlers are used to free resources on failure:

        // acquire resource
        try {
                // do something that might fail
                // free resource
        } catch (...) {     // any exception
                // free resource
                throw;      // rethrow the exception
        }
This can often be avoided, using the resource acquisition as initialization technique.

Resource management

A typical pattern of resource use

Resources must often be released in the opposite order to acquisition:

        // acquire resource 1
        // ...
        // acquire resource n

        // use resources

        // release resource n
        // ...
        // release resource 1
Just like locally allocated data!

Resource acquisition as initialization

Introduce a resource management class with

Introduce a locally allocated object of this class when the resource is acquired, and the resource will be automatically released. Moreover resources will be released in the correct order.

Example: file streams

Example: storage management

The following class manages the deletion of dynamically allocated Point objects:

        class PointManager {
                Point *ptr;

        public:
                PointManager(Point *p) : ptr(p) {}

                ~PointManager() { delete ptr; }
        };

Using the PointManager

Whenever a Point that is only required for this block is dynamically allocated, make a local PointManager to manage it:

        Point *p1 = new Point(20,30);
        PointManager m1(p1);

        Point *p2 = window->get_middle();
        PointManager m2(p2);
On leaving the block (normally, via return or by an exception), m2 will be destroyed, which deletes p2, and then m1, deleting p1.

Generic storage management

The standard header <memory> provides a class auto_ptr. Here is a simplified version:

        template <typename T> class auto_ptr {
                T *_ptr;

        public:
                auto_ptr(T *ptr) : _ptr(ptr) {}

                ~auto_ptr() { delete _ptr; }
        };
(More to come later)

Using auto_ptr

More convenience

We add the following operator definitions to the auto_ptr class:

        T & operator*() { return *_ptr; }
        T * operator->() { return _ptr; }
Then we can use the auto_ptr as a proxy for the pointer:
        auto_ptr<int> ip(new int);
        *ip = 3;

        auto_ptr<Point> pp(new Point(20,30));
        pp->x = 4;
        pp->y = 5;

Completing auto_ptr

Smart pointers

auto_ptr is an example of a smart pointer: it looks like pointer, but does something extra. Some other examples:

reference counting
the proxy could keep a count of the number of references to a dynamically allocated object, and delete it when the last one is destroyed.
persistent data
the proxy could read data from a file on first use, and save it in the file on destruction.
virtual object
the proxy could delay creating a complex object until it is used (and if the object is never used, avoid creating it).

The Proxy pattern

More generally, a proxy is any object that is interposed between the client and some other object. Some other uses:

wrapper
the proxy may provide consistent access to foreign language data.
protection
the proxy may provide more limited access to the object, for greater security.
handle
the proxy may represent an object in a different address space, e.g. an operating system object, a graphical system object, or an object on another machine.

Further reading

Major Differences between Java and C++

Things you should be able to do

(to be continued)

More things you should be able to do

(to be continued)

Even more things you should be able to do