Since delete [] knows array sizes, why is this information not available?
Asked Answered
Z

4

7

When I allocate a dynamic array in C++ (T * p = new T[n]), I use delete [] p to free the allocated memory. Obviously, the system knows the array size (in order among other things to call n times T's destructor). This is discussed elsewhere. For instance How does delete[] “know” the size of the operand array?. This is implemenation details.

But why was it not decided to make this information available?

Thx

Zabrina answered 10/1, 2018 at 14:3 Comment(6)
Because std::vector. Seriously, that's what it's trying to encourage you to use.Griffith
You could have a look at Doug Mclean comment in this answer https://mcmap.net/q/24908/-how-does-delete-quot-know-quot-the-size-of-the-operand-arrayLatonya
so I have a declaration of new [] that always allocates 1024 items. no matter how many were passed - on attempting to get more, I throw a bad_alloc. The size just isn't available anymore. That's the implementation detail that breaks your exampleMouthpart
For example, if I make an app where I know that most of my objects are going to be alive up to the end of execution and I know that the maximum size of memory I'm going to need is going to be relatively small I can just pre-allocate a chunk of memory and pass out pointers in it with overloaded new and new[], then do a no-op operator delete and operator delete[] because I know I won't need that memory again. I wouldn't need to store the size of each allocation, just a next pointer.Payola
@Mouthpart -- no; operator new[] doesn't allocate items; it allocates space for items. new X[whatever] doesn't care how much space was actually allocated, as long as it's at least the amount that the compiler requested in the call to operator new[]. The compiler generates code to keep track of the number of objects that were constructed, usually in "extra" memory at the beginning of the allocated block.Rubric
@PeteBecker maybe I didn't describe it very well... my point was The compiler generates code to keep track of the number of objects that were constructed doesn't need to be true - it is as a rule of thumb, but it doesn't have to. In the case it doesn't, the size just isn't available.Mouthpart
P
4

delete[] might not necessarily know the exact array size. It might over-allocate for example, or do something else entirely bizarre yet conformant with the standard.

Facetiously the answer could also be on the lines that nobody has managed to convince the standards committee of the merits of the idea; perhaps sizeof[](p) could be the proposed syntax? sizeof is already a keyword, already has a runtime-evaluable flavour in C so it's not an enormous leap to envisage an equivalent in C++, and my [] distinguishes from sizeof(pointer type).

Photomultiplier answered 10/1, 2018 at 14:17 Comment(2)
+1. A concrete example new char[7] on almost all modern optimising heaps will go through a low fragmentation/bucketing heap in the 8 byte bucket and have no idea about its size if queried. Storing the size when no one (currently) needs to know isn't optimal.Solidary
Is there any chance of sizeof[](p) conflicting with lambda syntax somehow?Derma
S
2

It would inhibit optimisations where knowledge of array size is not nessesary:

int* foo = new int[...];
. . .
delete[] foo;

As int is a trivial type and does not have a destructor, compiler do not need to know how many ints are there. Even if it is an array of 1 int in 4 MB memory chunk.

const MyType* const foo = new MyType[. . .];
. . .
delete[] foo;

Here compiler knows size of the array, pointed by foo, and it knows, that it cannot change legally. So it just can use that information directly, and do not store amount of items in allocated array.

Snapback answered 10/1, 2018 at 14:16 Comment(0)
G
0

Because new is not the only source for dynamic array (which share the same signature with pointer to objects), it has to be compatible with C.

Think about this:

void seem_good(MyStruct* d) {
  mess_with(d[3]);
}

The compiler have no way to perform check if it wanted to be called from other languages.


By the way, when inter-operation with other languages is not needed, C++ has its own solution: std::array.

Government answered 10/1, 2018 at 14:10 Comment(4)
But how does this answer why there can't be a function sizeofallocation(void *p) that might as well be UB for pointers that didn't come from new or new[]. Can you elaborate?Payola
A good spec should try to eliminate ambiguous keyword. sizeofallocation(void *p) is asking for trouble when programmer pass in ordinary pointers. Even you introduce new keyword that's paired with new/delete and UD for incompatible pointer, it only provide a feature that is already solved by std::array.Government
@Non-maskableInterrupt -- delete [] p; is also asking for trouble when the programmer passes a pointer that wasn't returned by new[]. The possibility that something could be misused is not a reason for not having it.Rubric
The programmer needs to keep track of what pointers they've newed anyway so I don't believe that's an issue here. And std::array doesn't solve run-time determined sizes. For the record, I don't think such a function should exist, I was just asking about your answer because I don't get it.Payola
S
0

It's implementation-specific. One possible way the runtime tracks the size is to store it in memory just before the returned pointer, but its not something you can count on. I was once tasked with tracking (heap) memory usage so I did exactly this - wrote a custom allocator that allocated some extra bytes, stored the size and returned an offset pointer. When you delete you need to "unoffset" the pointer, do what you need to with the size, then delete.

Stromberg answered 10/1, 2018 at 14:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.