Avoiding Memory Leaks using Boost Libraries

Using boost::scoped_array

When we want to dynamically allocate an array of objects for some purpose, the C++ programming language offers us the new and delete operators that are intended to replace the traditional malloc() and free() subroutines that are part of the standard library :

int* ptr = new int[ 500 ];

// do stuff using the array...
// ... etc
// ... and remember to release when finished

delete [] ptr;
ptr = NULL;

The new operator attempts to allocate sufficient memory for the data, and if successful it returns the address of the allocated memory. When the delete operator is called the object’s destructor is called, if it has one, before freeing up that object’s memory.

Forgetting to use delete to release allocated memory can cause memory leaks. In some cases this will cause the system to page virtual memory to the hard drive and eventually crash the application when the system’s resource limits are exceeded.

The boost scoped_array class template offers a simple means of storing your pointer to a dynamically allocated array and guarantees its deletion when you are finished. It cannot be used in C++ library containers however, neither can it be used to hold a pointer to a single object: for this use a scoped_ptr.

Simple example below:

#include <boost/scoped_array.hpp>;

// 1. Use scoped_array to automatically free memory
void func1( int size )
{ 
    boost::scoped_array< int >ptr( new int[size] );
}

// 2. Use delete operator
void func2( int size )
{    
    int* ptr = new int[ size ];
    delete[] ptr; 
    ptr = NULL; 
}

int main( int argc, char* argv[] )
{
    func1( 200 );
    func2( 200 );
    return 0;
}

Using Boost smart pointers:

The following example shows how classes are lost in memory once your vector goes out of scope:

#include <vector>

struct 
{
    virtual ~A() {}
};

struct B: A
{  };

typedef std::vector container;

void foo(void)
{
    container c;

    for ( int i = 0; i < 100; ++i )
        c.push_back( new B);
} // leaks here!

int main(void)
{
    foo();
}

Far better is if the pointers delete themselves, by using a smart pointer, like boost::shared_ptr:

#include <boost/shared_ptr.hpp>
#include <vector>

struct A
{
    virtual ~A() {}
};

struct B: A
{        
};

// hold smart pointers
typedef boost::shared_ptr BasePtr;
typedef std::vector container;

void foo(void)
{
    container c;

    for (int i = 0; i < 100; ++i)
        c.push_back( BasePtr( new B ) );

    // free memory
    // done automatically
}

int main(void)
{
    foo();
}

Leave a Reply