How Could Pairing New[] With Delete Possibly Lead to Memory Leak Only

How could pairing new[] with delete possibly lead to memory leak only?

Suppose I'm a C++ compiler, and I implement my memory management like this: I prepend every block of reserved memory with the size of the memory, in bytes. Something like this;

| size | data ... |
^
pointer returned by new and new[]

Note that, in terms of memory allocation, there is no difference between new and new[]: both just allocate a block of memory of a certain size.

Now how will delete[] know the size of the array, in order to call the right number of destructors? Simply divide the size of the memory block by sizeof(T), where T is the type of elements of the array.

Now suppose I implement delete as simply one call to the destructor, followed by the freeing of the size bytes, then the destructors of the subsequent elements will never be called. This results in leaking resources allocated by the subsequent elements. Yet, because I do free size bytes (not sizeof(T) bytes), no heap corruption occurs.

C/C++ delete vs delete[]

  • delete: This frees the memory currently allocated by the pointer the delete is performed upon. It only deletes the memory pointed to by the first variable.

  • delete []: This frees the memory allocated for the whole array. An array consists of several variables - delete frees memory only allocated for the first variable, while delete [] does the whole thing.

A good way to think of it is considering delete as an instruction while delete [] as a loop; where the array is looped through and delete is called individually on each variable in the array. This is NOT how it works in reality (the real workings are a bit more complicated), but is a good way to understand the diff.

The destructor is called on all objects, because in some cases such as in the case of an array of objects that contain pointers, calling the destructor on only the first element doesn't free all memory.

Difference between pointer to a new element and new array?

When using new [] some c++ implementations will track the size of the allocation of the array in the address before the pointer returned. This is an implementation detail not defined by the standard.

The following answer describes this possible implementation in a little more detail: How could pairing new[] with delete possibly lead to memory leak only?

You must always match new with delete and new [] with delete []. It is Undefined Behavior to mix these.

deleting c++ array from heap and memory leak

Calling delete on an array without using [] results in Undefined Behaviour. The Undefined Behaviour might be that the array is correctly deleted, which appears to be what you observed. You can't rely on this, however.

Is delete p where p is a pointer to array always a memory leak?

delete p, where p is an array is called undefined behaviour.

Specifically, when you allocate an array of raw data types (ints), the compiler doesnt have a lot of work to do, so it turns it into a simple malloc(), so delete p will probably work.

delete p is going to fail, typically, when:

  • p was a complex data type - delete p; won't know to call individual destructors.
  • a "user" overloads operator new[] and delete[] to use a different heap to the regular heap.
  • the debug runtime overloads operator new[] and delete[] to add extra tracking information for the array.
  • the compiler decides it needs to store extra RTTI information along with the object, which delete p; won't understand, but delete []p; will.

Possible memory leak?

You should be using delete[]. Memory allocated with new[] MUST be deallocated with delete[].

Reference:

C++03 Standard: § 3.7.4.2-3

If a deallocation function terminates by throwing an exception, the behavior is undefined. The value of the first argument supplied to a deallocation function may be a null pointer value; if so, and if the deallocation function is one supplied in the standard library, the call has no effect. Otherwise, the value supplied
to operator delete(void*) in the standard library shall be one of the values returned by a previous invocation of either operator new(std::size_t) or operator new(std::size_t, const std::nothrow_-t&) in the standard library, and the value supplied to operator delete[](void*) in the standard library shall be one of the values returned by a previous invocation of either operator new[](std::size_t) or
operator new[](std::size_t, const std::nothrow_t&) in the standard library.

C++ Will this cause a memory leak?

Each call to new must be paired with a call to delete to avoid a memory leak (or new[] and delete[]).

How to delete the memory depends on what you're doing but since you don't keep access beyond the for-loop then you could easily delete it within the body of the for-loop.

for (int i = 0; i < 10; ++i)
{
array = getArray();
/* do something with 'array' */
delete[] array;
}

Better yet, why not use std::vector<int> and avoid directly performing any memory allocation?

Edit:
As @Niall mentions in the comments you should also familiarize yourself with std::unique_ptr (assuming you're compiler supports it). It uses RAII (Wikipedia link, cppreference link) to automatically handle the memory management. For example, std::unique_ptr<int[]> which will automatically call delete[] once the class goes out of scope.



Related Topics



Leave a reply



Submit