Saturday, June 12, 2010

RAII vs finally

Since I'm pretty new to C++, I wasn't too deeply familiar with RAII; like most Schemers I just thought of it as "C++'s version of dynamic-wind."

This week I learned an important distinction between C++ destructors and Java's finally. The latter, of course, unilaterally executes when the body terminates, regardless of how or when it terminates. The thing that gives destructors more expressiveness for dealing with cleanup is that they only execute for the objects that have been initialized. This means that if control exits a block after only half of the stack-local objects have been constructed, only those half of the objects have their destructors invoked. With finally, all that bookkeeping is the responsibility of the programmer.

(That said, I still see RAII used all over the place to construct awkward, special-purpose classes whose sole purpose is to run some cleanup code. In these cases, having to create a named object and a named class to go along with it is pretty perverse.)

7 comments:

Jeremy Fincher said...

The other major benefit of RAII over a "finally" block is that the former cannot be forgotten: programmers can easily write poor code by forgetting a finally block, but they cannot make the same mistake if the functions they call return only resources managed by classes with appropriate destructors.

steck said...

Lately, I've thought of Dorothy's departure from Oz as a non-local exit, like an exception throw or continuation invocation, combined with resource/object cleanup.

This particular metaphor is aided by the fact that Kansas begins with a `k'. And you can think of the words "I'm melting!" as the sound of destructors in action.

tonyg said...

I like Scheme's call-with-input-file (and friends) and Python's "with" statement as approaches to this problem. Both are used to bound regions in which a resource is available for use, with automatic cleanup as appropriate for the type of control transfer used to exit the block. I guess they share some of the problems of RAII, actually, with respect to the need for out-of-line pieces of code for resource management. Does "nested finally" help avoid the manual bookkeeping you mention? Have you been considering any alternatives that combine the virtues of both RAII and finally?

Jeff Foster said...

(That said, I still see RAII used all over the place to construct awkward, special-purpose classes whose sole purpose is to run some cleanup code. In these cases, having to create a named object and a named class to go along with it is pretty perverse.)

You can get rid of some of this boilerplate with smart pointer classes that take a function to call when the pointer goes out of scope. Something like boost::shared_ptr allows you to pass a function in to be called when it goes out of scope.

Sage said...

steck - that is inspired! Hope you don't mind but i'm having that little visual image to help my memory along as well!

verte said...

We recently had a very interesting discussion on this subject on cap-talk that you might enjoy: http://www.eros-os.org/pipermail/cap-talk/2011-March/thread.html#14632

3D4PC-Ryan-Newby-3D- said...

Very interesting but over my head, Hardware Man.