Saturday, 14 July 2007

Don't ever mix Arrays with auto_ptr !

This article is in response to one of the comments for my previous article about auto_ptr.

auto_ptr which is provided by the standard C++ library wont work with arrays. It's best to avoid using auto_ptr for arrays.

What is the problem?

To understand the problem, let's take a loot at C++'s memory management background. We all know that, any "new" statement we use for dynamically creating object should be accompanied with a call to "delete" for deleting that object.

CMyClass *p = new CMyClass; //Dynamically create an object

// some other processing
...

delete p; // delete the object  

Also, if we are allocating an array of objects using new[], that must be freed using delete[] operator, which frees up all the dynamically allocated objects.

CMyClass *p = new CMyClass[5]; //Dynamically create array of objects

// some other processing
...

delete[] p; // delete the objects  

In case of auto_ptr, the destructor will just do a delete on the embedded pointer member variable.

auto_ptr::~auto_ptr()    // Destructor  
{
    delete ptr;  // free the memory
}

There's no way for auto_ptr to intelligently do delete or delete[] based on the scalar or vector dynamic objects pointed by the member pointer.

If we do

auto_ptr<int> obj(new int[10]);

When obj goes out of scope, the destructor will be called and only delete will be done on the pointer. Which ideally had to be delete []. This causes leak and may cause undefined behavior.

Its always recommended to avoid using auto_ptr with arrays.

There are few solutions proposed for this problem by Herb Sutter here.

3 comments:

Unknown said...

There are some alternatives instead of using auto_ptr for dynamic allocation arrays:

(i) Avoid self memory management and instead use std::vector<> / std::deque<> for dynamic arrays.

(ii) There are smart pointers with different deallocation policies in the boost library:
- for objects there are boost::shared_ptr and boost::scoped_ptr (deleting by delete)
- for arrays there are boost::shared_array and boost::scoped_array (deleting by delete[]). They might not be the right choice if you don't want the reference count overhead of shared ownership which really should not be required when talking about auto_ptr<>s but if that's not an issue to worry about, it should work fine.

(iii) Write your own smart pointer : auto_ptr_array<> (same implementation as std::auto_ptr<>) just that it uses array form of delete instead of delete.

Internet marketing said...

Thanks for sharing.Well the number of elements in an array is a fixed number but it can also be readjusted dynamically.The array size limit is upper limit plus 1 because the index begins from 0.

Anonymous said...

Informative!