6

I understand that, when we write delete [] on a pointer created by a corresponding new [], the program will look for the accounting information on the array and find out the array's element size (a counter). Then the program invokes the element's destructor on each of them. Finally memory (what memory??) is deallocated by a function named operator delete.

What I am asking is whether delete[] will deallocate the entire memory, allocated by the new[] expression, in one shot because that information (total amount of memory) is available after all elements are destroyed, or will it successively deallocate the memory occupied by the array elements that it has invoked destructors on?

A related follow-up quesion is asked Does delete (non array form) know the total amount of memory allocated by either new or new[]

Community
  • 1
  • 1
Rich
  • 1,669
  • 2
  • 19
  • 32
  • 2
    I would have thought the answer to your question depends on the implementation by the compiler and operating system – Ed Heal Sep 10 '15 at 16:58
  • 3
    Does `free` need to know the size of the allocation returned by `malloc`? – Kerrek SB Sep 10 '15 at 17:02
  • 2
    Does the C++ standard say anything about the supposed behavior of `delete` expressions? – Rich Sep 10 '15 at 17:03
  • Your final question makes no sense, since `delete pi` causes undefined behaviour, so you cannot ask us to define the behaviour for you. – Kerrek SB Sep 10 '15 at 17:03
  • 1
    possible duplicate of [How does delete\[\] "know" the size of the operand array?](http://stackoverflow.com/questions/197675/how-does-delete-know-the-size-of-the-operand-array) – BartoszKP Sep 10 '15 at 17:05
  • 1
    Could you elaborate more on what don't you understand from the linked question? It explains explicitly a possible mechanism that allows to store the information on the amount of memory to deallocate. – BartoszKP Sep 10 '15 at 17:06
  • 7
    You're asking a bunch of question in one, which causes confusion. Please ask one. – edmz Sep 10 '15 at 17:09
  • @KerrekSB all I am concerned is whether `delete` and `delete[]` deallocate the entire memory in one shot in the end. Is that defined behavior? – Rich Sep 10 '15 at 17:12
  • @rich - What do you mean by deallocate? By the OS? Put back into general circulation for the compiler? – Ed Heal Sep 10 '15 at 17:14
  • 1
    @Rich: both a `delete` and a `delete[]` expression (provided it is valid) performs (at most) *one* deallocation (there are arcane details relating to "extendable allocations" in C++14 that we shall ignore here), that's correct. They do so by calling a suitable function `operator delete` or `operator delete[]`. – Kerrek SB Sep 10 '15 at 17:16
  • @EdHeal I mean the memory is reclaimed and become available to the programs for possible further memory allocation. I am not sure if it is some runtime system's job or the OS's. – Rich Sep 10 '15 at 17:17
  • I don't understand why would you need only information whether the value is stored somewhere. There is no standard way to obtain it, even if it is somewhere in there. Therefore it's pointless to ask unless you are going to narrow down scope to specific compiler. Memory is abstracted from users. It might not be stored. For example there are some implementations that never reclaim memory. So free is essentially a no-op. Then you would need to have it. – luk32 Sep 10 '15 at 17:19
  • The compiler may just hang on to the memory that has been given to it from the OS. Or may let the OS have it back. It depends on the implementation and the runtime environment. So the question is why worry? The compiler/OS does its job. The compiler can implement such things in a multitude of ways – Ed Heal Sep 10 '15 at 17:19
  • @KerrekSB On my final question: it is an example of my second follow up question. If delete (non array form) also knows the total amount of memory allocated by `new[]`, and if the `new`ed array element doesn't hold extra memory or has trivial destructor, can `delete` do the job of `delete[]` without leaking memory? – Rich Sep 10 '15 at 17:32
  • @Rich: No. It's undefined behaviour to evaluate such an expression. – Kerrek SB Sep 10 '15 at 17:34
  • 1
    @Rich As advised by black, **don't** add "follow up questions", "second questions" and "additional questions". Focus on one thing - otherwise you're confusing people, and make the site less readable and less helpful. – BartoszKP Sep 10 '15 at 17:35
  • @BartoszKP Ok, I will ask my second question as a separate one. – Rich Sep 10 '15 at 17:38
  • 3
    @Rich Is the reason why you're asking these question is because you have inherited a badly coded program that throws together array `new` with non-array `delete`'s and vice-versa, and that you're hoping you don't need to make changes to such a program? Otherwise, why not write the correct pairings of `new`, `new[]`, `delete`, `delete[]` and let the compiler deal with this? – PaulMcKenzie Sep 10 '15 at 17:39
  • Or better still use vectors and smart pointers instead – Ed Heal Sep 10 '15 at 17:43
  • Indeed. Just do it correctly and don't worry about what you can "get away with." – Zan Lynx Sep 10 '15 at 17:43
  • @PaulMcKenzie No. I actually just want to understand the mechanics of how delete[] works. and if in the end, delete[] deallocates all the memory, why would you care if the all the elements are destructed, or only some of the elements are (of course, this is assuming the elements don't further contain dynamic memory). – Rich Sep 10 '15 at 17:51
  • @rich - The mechanics depend on the OS/implementation of the compiler/the run time environment. – Ed Heal Sep 10 '15 at 17:52
  • @Rich "Why is the standard like this" questions are often unanswerable. The C++11 "rationale" document, if you can find it (casual googling does not bring it up) *might* address this point, but it probably doesn't. – zwol Sep 10 '15 at 17:55

3 Answers3

2

All of the memory will be released to the underlying allocator at once. This is mandated by the C++ standard, although not especially clearly. N3337 is the closest approximation to the official C++11 standard available online for free. Look at section 5.3.5, [expr.delete], which spells out the code that an invocation of delete[] expands to. In particular, operator delete[] is called once in step 7, after destructors have been invoked for all elements of the array (step 6).

You can also deduce this behavior from the wording in 18.6.1.2 [new.delete.array] regarding what pointers are valid to pass to operator delete[]: "... shall be the value returned by an earlier call to operator new[] (... caveats ...)". Since operator new[] returns one pointer to an entire array, operator delete[] must also be invoked once for an entire array.

zwol
  • 135,547
  • 38
  • 252
  • 361
1

5.3.5/2:

In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined.

This clearly shows us that the behavior in your proposed situation is undefined by the standard, which leaves "not leaking memory" or "leaking memory" as the two most likely undefined behaviors (it seems that heap corruption could be a much less likely third possibility just for completeness). Just don't write such code and you avoid possible problems.

Mark B
  • 95,107
  • 10
  • 109
  • 188
0

In practice your example

auto pi = new int[10];
...
delete pi;

works just fine and is quite common in working programs. I'll trust those here who looked it up in the standard, that it is undefined behavior. So I won't suggest you take advantage of the fact that it routinely works. In practice, the allocator keeps track of the total size and deallocation frees the correct total size, so pairing new[] with delete only causes the destructors of elements past the zeroeth to fail to be called and does no harm for arrays of objects with trivial destruction. But coding undefined behavior is not a great idea even when you are confident every compiler behaves OK for that particular UB.

Edit: now that you removed all that from your question to ask only the more trivial part of the original question:

I assume the standard does not go into any such detail, so an implementation could do either. But I'm also confident any real implementation frees the entire contiguous chunk in one shot after calling all the destructors. (The implementation would also have no choice but to do it the sane way for cases where delete[] is overridden)

JSF
  • 5,281
  • 1
  • 13
  • 20
  • The follow-up question is moved to http://stackoverflow.com/questions/32508952/does-delete-non-array-form-know-the-total-amount-of-memory-allocated-by-either – Rich Sep 10 '15 at 18:14