17

I am curious how delete[] figures out the size of the allocated memory. When I do something like:

int* table = new int[5];
delete[] table;

I understand that the memory of the table is freed. But what would happen if I reassigned the pointer to some different table.

int* table = new [5];
int* table2 = new [9];
table = table2;
delete[] table;

Will I free a table of the size 5 or 9? I am interested in how new[] and delete[] share information about their size. Or maybe I am missing something essential here.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Lucas
  • 13,679
  • 13
  • 62
  • 94
  • Duplicate (more or less) of http://stackoverflow.com/questions/377178/how-does-the-standard-new-operator-work-in-c/377208 – Binary Worrier Jun 10 '09 at 14:06
  • 7
    I disagree, this is more specific. – Doug T. Jun 10 '09 at 14:11
  • As a side note, and as mentioned in the answers, this is implemention-specific stuff. That means that you should not rely on the way it is done to extract the size of the array, as it could change from compiler to compiler, and from compiler version to compiler version. – Raphaël Saint-Pierre Jun 10 '09 at 14:13
  • Ah... I see there's another question with almost the same wording different from Binary Worrier's comment. – Doug T. Jun 10 '09 at 14:16
  • You leaked memory (5 integers worth) - but freed 9 integers. – Jonathan Leffler Jun 10 '09 at 14:39
  • 3
    This is very much a duplicate of http://stackoverflow.com/questions/197675 – Jonathan Leffler Jun 10 '09 at 14:39
  • Sorry, for duplicating the question. – Lucas Jun 10 '09 at 20:10
  • @JeandardClaboudin "_this is implemention-specific stuff_" just as vtables - yet **every** C++ compiler uses vtables. When there is really only one reasonable way to do something, you can bet that every compiler does it this way, with only minor variations. – curiousguy Sep 29 '11 at 22:43
  • 1
    @curiousguy: that was three years ago. But http://msdn.microsoft.com/en-us/library/bebs9zyz(v=vs.80).aspx has some awesome info about how MSVC does their debug heaps. – Mooing Duck Sep 29 '11 at 22:51
  • Possible duplicate of [How does delete\[\] "know" the size of the operand array?](https://stackoverflow.com/questions/197675/how-does-delete-know-the-size-of-the-operand-array) – Cœur Jul 09 '18 at 14:07

8 Answers8

24

It would delete an array of size 9. It deletes the array pointed to by the pointer.

It is unspecified how the size information is stored, so each compiler may implement it in a different way, but a common way to do it is to allocate an extra block before the array. That is, when you do this:

int* table = new int[5];

it actually allocates an array of 6 integers, and stores the array size in the first element. Then it returns a pointer to the second element. So to find the size, delete[] just has to read table[-1], basically.

That's one common way to do it, but the language standard doesn't specify that it must be done in this way. Just that it has to work.

Another approach might be to use the address of the array as a key into some global hash table. Any method is valid, as long as it produces the correct results.

jalf
  • 243,077
  • 51
  • 345
  • 550
  • 1
    Thank you, this explanation makes a lot of sense to me. Although I would have liked to choose multiple answers as the accepted answer. – Lucas Jun 10 '09 at 20:11
20

Section 16.14 of the C++ FAQ lite answers this:

There are two popular techniques that do this. Both these techniques are in use by commercial-grade compilers, both have tradeoffs, and neither is perfect. These techniques are:

* Over-allocate the array and put n just to the left 
  of the first Fred object.
* Use an associative array with p as the key and n as the value.
Doug T.
  • 64,223
  • 27
  • 138
  • 202
  • 1
    Could you cite one compiler with the associative array? – curiousguy Sep 29 '11 at 22:44
  • @curiousguy According to the link in the FAQ CFront uses this: http://www.parashift.com/c%2B%2B-faq-lite/compiler-dependencies.html#faq-38.8 – Doug T. Sep 30 '11 at 09:46
  • You mean the compiler that never had modern templates, that was already irrelevant 15 years ago, with [last release in 1991](http://www.softwarepreservation.org/projects/c_plus_plus/index.html#cfront): "_Bjarne Stroustrup notes, "A warning that Cfront 3 is pre-standard and emphatically not recommended for use or further development might be in place."_" – curiousguy Sep 30 '11 at 13:03
  • @curiousguy Yup that one. The C++ FAQ probably needs an update on this point. – Doug T. Sep 30 '11 at 13:07
  • 1
    Does anybody know how it works in gcc for x86 and ARM and Microsoft Visual Studio compilers? – killdaclick Sep 16 '13 at 15:28
4

How this is done is a compiler specific detail. But the call to delete[], assuming no memory corruption, will always delete the right number of elements. There are several ways to achieve this but one simple way is to hide the length in the memory.

Here's a nice and simple way to implement this for demonstration purposes. Say your code calls new int[10]. Instead of allocating 10 * sizeof(int), the compiler allocates (10 * sizefo(int))+sizeof(size_t). It then returns a pointer to you which is offset size_t from the start. Inside that initial size_t space it writes the number 10. Now when you call delete[] and pass in a pointer, the compiler just goes backward size_t bytes and finds the number of elements to delete.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
2

How delete[] works is implementation-dependent, but the global new operator associates a descriptor with the allocated memory in some way (in most cases, it's prepended to the allocated memory, or stored in a lookup table). The descriptor contains the actual size of the memory that was allocated.

In your second code example, delete[] will correctly delete the nine-element array of int, and the original five-element array will be leaked.

MattK
  • 10,195
  • 1
  • 32
  • 41
1

The mechanism is implementation-dependent, but it will not be "fooled", by you reassigning the pointer in your example. It will deallocate the array of size 9, just like you told it to (and in this case there will be a memory leak because the array of size 5 now has nothing pointing to it).

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
0

in the new[]/delete[] case, what happens memory-wise is same/similar to what happens in new/delete case... the size info is stored inside the (larger) allocated block itself . what is interesting for arrays is that it also uses the size info to know how many objects to call destructors on .

mhk
  • 345
  • 2
  • 7
0

My guess is that new[] actually allocates more data than it seems. It probably has a few bytes before the pointer that is returned that tells how many items are in the array.

Robert Deml
  • 12,390
  • 20
  • 65
  • 92
0

You could imagine that the system store the size of the table in a structure like this:

struct MemoryAllocated
  {
  size_t sizeOfMemory;
  char* yourData;
  }

each type your allocating some memory, the system returns a pointer to 'yourData'. And each type your memory is 'free', the system shift the pointer to get the 'sizeOfMemory'. See also std::allocator

Pierre
  • 34,472
  • 31
  • 113
  • 192
  • This answer only creates confusion. How would the system "shift" `yourData` to reach `sizeOfMemory` ? – 0xF Apr 30 '19 at 14:41