Shared pointers, and why you should use them

NOTE: The ideas expressed below are in part based on the book Effective C++ by Scott Myers. He uses auto_ptr in his example, but essentially the lesson is the same.

Let’s face it: pointers are dangerous. If you allocate something, you always have to make sure you deallocate it, or you will end up with a memory leak. Under most circumstances this is easy; for every new, you should have a matching delete. However when dangerous things like exceptions are thrown into the mix, making sure to free your memory can become a daunting task, and you may end up with a lot of code duplication.

Here’s an example.

void foo()
{
Silly* mySilly = CreateSilly();

/* Do some stuff with mySilly here. */

delete mySilly;
}

This kind of code can be common especially if you’re having to use old C libraries. Notice that you’re expected to delete your created Silly yourself. All of this looks pretty standard, but what if somewhere in the body of the function an exception gets thrown? When an exception is thrown in C++, all local variables declared have their destructors called, but no such claim is made for variables declared on the free store with new/delete or malloc/free. Essentially in the above code, your mySilly may never be freed!

One way to fix this is with a try/catch block, as seen below:

void foo()
{
Silly mySilly = CreateSilly();

try
{
/* Here be dragons */
}
catch (...)
{
delete mySilly;
}

delete mySilly;
}

Safe, but notice the code duplication? That should set off some red flags. Now an ideal solution would be to have some sort of way to delete mySilly in a 100% assured way, and that is where the RAII pattern comes into play.

RAII stands for “Resource Allocation is Initialization”. Essentially any time you need to access a resource, such as memory on the free store, a file pointer, an area of shared memory, etc. you should be wrapping it in an object such that:

  1. Your resource can be allocated safely in a constructor
  2. Your resource can be safely deleted in a destructor.

And this is where smart pointers come into play. The boost library has some amazing things, but one of the most useful parts of boost is the shared_ptr class. shared_ptr is a templated class whose job is to allocate something in its constructor, and free it in its destructor. Because of operator overloading, shared_ptr behaves semantically the same as a raw pointer, and it uses reference counting internally to ensure that nothing gets deleted if there are multiple shared pointers pointing at the same piece of data.

Our code example above becomes this:

void foo()
{
shared_ptr<Silly> mySillyPtr(CreateSilly());

/* Do some dangerous stuff here. */

}

If our dangerous section throws an exception, the destructor of mySillyPtr gets called, which frees the memory (if it’s the only pointer to it), and thus no memory leaks occur. Notice how much simpler the above code is compared to the try/catch code.

The boost shared_ptr can be used either by downloading the boost library and including the file <boost/shared_ptr.hpp> or it can be obtained in the <tr1/memory> header file, since shared_ptr may find its way into the next C++ standard update.

Shared pointers are yet one more reason to use the many new modern features of C++ over the old C techniques as often as you can. Properly coded C++ should leak no memory at all :)

About Bryan St. Amour

Why yes! I do own this place!
This entry was posted in Code and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>