5

Possible Duplicates:
How could pairing new[] with delete possibly lead to memory leak only?
( POD )freeing memory : is delete[] equal to delete?

Using gcc version 4.1.2 20080704 (Red Hat 4.1.2-48). Haven't tested it on Visual C++.

It seems that delete and delete [] works the same when deleting arrays of "simple" type.

char * a = new char[1024];
delete [] a; // the correct way. no memory leak.

char * a = new char[1024];
delete a; // the incorrect way. also NO memory leak.

But, when deleting arrays of "complex" type, delete will cause memory leak.

class A
{
public:
    int m1;
    int* m2; // a pointer!
    A()
    {
        m2 = new int[1024];
    }
    ~A()
    {
        delete [] m2; // destructor won't be called when using delete
    }
};
A* a = new A[1024];
delete [] a; // the correct way. no memory leak.

A* a = new A[1024];
delete a; // the incorrect way. MEMORY LEAK!!!

My questions are:

  1. In the first test case, why delete and delete [] are the same under g++?
  2. In the second test case, why g++ doesn't handle it like the first test case?
Community
  • 1
  • 1
jarjar
  • 67
  • 1
  • 2
  • How did you confirm that in the first case there is no memory leak and in both cases there are no memory errors? – neuront Aug 05 '11 at 08:33
  • Please carefully read this question - http://stackoverflow.com/q/1913343/57428 which explains all the reasons in great details. – sharptooth Aug 05 '11 at 08:33
  • 1
    It's likely that it DOES handle it the same as in the first case, as far as the memory freeing goes. Total allocation size is generally stored in the same manner in both cases, so the memory gets freed correctly. However, delete[] is designed to call destructors for every object allocated, whereas delete would only call it on the first object, i.e. a[0]. This is why the memory leak happens. The int arrays internal to the A objects are not freed, since the destructors are not called, but the initial allocation of A objects is freed correctly. Either way, this is unportable undefined behavior. – Kevin M Aug 05 '11 at 08:33

7 Answers7

10

This is all dependent on the underlying memory manager. Simply put, C++ requires that you delete arrays with delete[] and delete non-arrays with delete. There is no explanation in the standard for your behaviour.

What's likely happening however is that delete p; simply frees the block of memory starting at p (whether it is an array or not). On the other hand delete[] additionally runs through each element of the array and calls the destructor. Since normal data types like char don't have destructors, there is no effect, so delete and delete[] end up doing the same thing.

Like I said, this is all implementation specific. There's no guarantee that delete will work on arrays of any type. It just happens to work in your case. In C++ we call this undefined behaviour -- it might work, it might not, it might do something totally random and unexpected. You'd be best to avoid relying on undefined behaviour.

Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
6
char * a = new char[1024];
delete a; // the incorrect way. also NO memory leak.

No. It doesn't gaurantee No memory leak. It in fact invokes undefined behavior.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
3

delete and delete[] seemingly being equivalent in g++ is pure luck. Calling delete on memory allocated with new[], and vice versa, is undefined behaviour. Just don't do it.

Jörgen Sigvardsson
  • 4,839
  • 3
  • 28
  • 51
1

Because that's undefined behavior. It's not guaranteed to break but it's not guaranteed to work either.

Novikov
  • 4,399
  • 3
  • 28
  • 36
1

The delete expression calls the destructor of the object to be deleted before releasing the memory. Releasing the memory probably works in either case (but it's still UB), but if you use delete where you needed delete[], then you aren't calling all the destructors. Since your complex object itself allocates memory which it in turn releases in its own destructor, you are failing to make all those deletions when you use the wrong expression.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

they technically aren't the same, they just get optimized down to the same meaning on non-complex types. complex types require the vectorized delete so that the destructor can be called for every object in the array you delete (just like vectorized new for constructors).

what your doing just free's the memory like its a pointer array.

Necrolis
  • 25,836
  • 3
  • 63
  • 101
0

What is happening here is that when you call delete, the space taken up by the objects is deleted. In the case of chars, this is all you need to do (although it is still recommended to use delete[] because this is just g++. The actual behavior of calling delete on an array is undefined in the c++ standard.).

In the second example, the space taken up by you array is deallocated, including the pointer m2. However, what m2 is pointing to is not also deleted. When you call delete[] the destructor on each object in the array is called and then what m2 points to is deallocated.

jgeralnik
  • 126
  • 1
  • 7