Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::auto_ptr, delete[] and leaks

Why this code does not cause memory leaks?

int iterCount = 1000;
int sizeBig = 100000;
for (int i = 0; i < iterCount; i++)
{
   std::auto_ptr<char> buffer(new char[sizeBig]);
}

WinXP sp2, Compiler : BCB.05.03

like image 275
Mikhail Aksenov Avatar asked Jul 29 '09 07:07

Mikhail Aksenov


People also ask

What is the problem with auto_ptr?

auto_ptr cannot be used in STL containers because it has a copy constructor that does not meet requirements of container CopyConstructible. unique_ptr does not implement a copy constructor, so containers use alternate methods.

Why use auto_ ptr?

auto_ptr type is provided by the C++ standard library as a sort of smart pointer that helps to avoid resource leaks when exceptions are thrown.

What is std :: Auto_ptr?

std::auto_ptr auto_ptr is a smart pointer that manages an object obtained via new expression and deletes that object when auto_ptr itself is destroyed.

Why auto_ ptr cannot be used with STL?

The C++ Standard says that an STL element must be "copy-constructible" and "assignable." In other words, an element must be able to be assigned or copied and the two elements are logically independent. std::auto_ptr does not fulfill this requirement.


2 Answers

Because you're (un)lucky. auto_ptr calls delete, not delete []. This is undefined behavior.

Try doing something like this and see if you get as lucky:

struct Foo
{
    char *bar;
    Foo(void) : bar(new char[100]) { }
    ~Foo(void) { delete [] bar; }
}

int iterCount = 1000;
int sizeBig = 100000;
for (int i = 0; i < iterCount; i++)
{
   std::auto_ptr<Foo> buffer(new Foo[sizeBig]);
}

The idea here is that your destructor for Foo will not be called.


The reason is something like this: When you say delete[] p, the implementation of delete[] is suppose to go to each element in the array, call its destructor, then free the memory pointed to by p. Similarly, delete p is suppose to call the destructor on p, then free the memory.

char's don't have a destructor, so it's just going to delete the memory pointed to by p. In my code above, it is not going to destruct each element in the array (because it's not calling delete[]), so some Foo's will leave their local bar variable un-deleted.

like image 52
GManNickG Avatar answered Oct 10 '22 09:10

GManNickG


The auto_ptr will only live for the duration of the loop iteration and will release the object connected to it on iteration completion.

The compiler can see that in this case new[] can allocate space in the same way as new - without storing the number of elements anywhere since there's no need to call trivial char destructors - and that's why later when delete is called by the auto_ptr's destructor instead of delete[] it causes no problems since the memory block has actually been allocated in the new's way and that allocation can be paired with delete.

This is an example of a thing not to do. It's up to the compiler to decide whether to replace new[] with new. Using delete instead of delete[] and vice versa is undefined behaviour.

See Why would you write something like this? (intentionally not using delete [] on an array) for discussion of delete vs delete[].

like image 27
sharptooth Avatar answered Oct 10 '22 11:10

sharptooth