views:

2262

answers:

9

Foo* set = new Foo[100];
// ...
delete [] set;
You don't pass the array's boundaries to delete[]. But where is that information stored? Is it standardised?

+10  A: 

It depends on the implementation of your compiler.

The C++ FAQ lite has some more information on the subject.

luke
+1  A: 

This isn't something that's in the spec -- it's implementation dependent.

jeffm
+2  A: 

Because the array to be 'deleted' should have been created with a single use of the 'new' operator. The 'new' operation should have put that information on the heap. Otherwise, how would additional uses of new know where the heap ends?

Joel Coehoorn
+28  A: 

When you allocate memory on the heap, your allocator will keep track of how much memory you have allocated. This is usually stored in a "head" segment just before the memory that you get allocated. That way when it's time to free the memory, the de-allocator knows exactly how much memory to free.

QuantumPete

QuantumPete
Note that this only applies to array allocations in C++. All other allocations rely on the size of the type. Some libraries do store all allocation sizes, usually only in debugging mode.
Zan Lynx
There is absolutely no reason why this information should not be available to the programmer. I can pass a pointer to a function and free it, but to get the size myself in that same function I have to pass around an extra parameter. Does that make any sense?
Mark Ruzon
@Mark, it makes a *small* amount of sense, because in theory it does free the allocator to always store the size of the *allocated* block (which may differ from the size of the *requested* block). Certain allocator designs may need this information for their own purposes, or may not be sophisticated enough to use type information to track the size of non-array heap allocations, etc. Forcing the allocator to store the requested size (so that you wouldn't need to pass the array size yourself) might be a small encumbrance, but it could have performance impacts on conceivable allocator designs.
Doug McClean
Sorry, but this answer misses the point. What QuantumPete described is basically "How `free` knows how much memory to deallocate". Yes, the memory block size is stored "somewhere" by `malloc` (normally in the block itself), so that's how `free` knows. However, `new[]`/`delete[]` is a different story. The latter basically work on top of `malloc`/`free`. `new[]` also stores the number of elements it created in the memory block (independently of `malloc`), so that later `delete[]` can retrieve and use that number to call the proper number of destructors.
AndreyT
I.e. physically two counters are stored in the block: block size (by `malloc`) and element count (by `new[]`). Note, that the former cannot be used to calculate the latter, since in general case the size of the memory block can be larger than really necessary for the array of requested size. Also note that the array element counter is only needed for types with non-trivial destructor. For types with trivial destructor the counter is not stored by `new[]` and, of course, not retrieved by `delete[]`.
AndreyT
A: 

It is not standardized. In Microsoft's runtime the new operator uses malloc() and the delete operator uses free(). So, in this setting your question is equivalent to the following: How does free() know the size of the block?

There is some bookkeeping going on behind the scenes, i.e. in the C runtime.

Andre
Not true. Before calling free, the delete[] needs to call destructors first. For this knowing total allocations size is not enough. Actually new[] and delete[] works different for plain and destructed types in VC++.
Suma
+4  A: 

The information is not standardised. However in the platforms that I have worked on this information is stored in memory just before the first element. Therefore you could theoretically access it and inspect it, however it's not worth it.

Also this is why you must use delete [] when you allocated memory with new [], as the array version of delete knows that (and where) it needs to look to free the right amount of memory - and call the appropriate number of destructors for the objects.

Daemin
+4  A: 

A nice description of how this might work in practice is given by Raymond Chen:

http://blogs.msdn.com/oldnewthing/archive/2004/02/03/66660.aspx

Frederik Slijkerman
+1  A: 

It's defined in the C++ standard to be compiler specific. Which means compiler magic. It can break with non-trivial alignment restrictions on at least one major platform.

You can think about possible implementations by realizing that delete[] is only defined for pointers returned by new[], which may not be the same pointer as returned by operator new[]. One implementation in the wild is to store the array count in the first int returned by operator new[], and have new[] return a pointer offset past that. (This is why non-trivial alignments can break new[].)

Keep in mind that operator new[]/operator delete[]!=new[]/delete[].

Plus, this is orthogonal to how C knows the size of memory allocated by malloc.

MSN

MSN
+1  A: 

Basically its arranged in memory as:

[info][mem you asked for...]

Where info is the structure used by your compiler to store the amount of memory allocated, and what not.

This is implementation dependent though.

Francisco Soto