Without going into the specifics of a specific implementation here, the intuitive reason behind the crash can be explained simply by considering what delete[]
is supposed to do:
Destroys an array created by a new[]
-expression
You give delete[]
a pointer to an array. Among other things, it has to free the memory it allocated to hold the contents of that array after.
How is the allocator know what to free? It uses the pointer you gave it as a key to look up the data structure which contains the bookkeeping information for the allocated block. Somewhere, there is a structure which stores the mapping between pointers to previously allocated blocks and the associated bookkeeping operation.
You may wish this lookup to result in some kind of friendly error message if the pointer you pass to delete []
was not one returned by a corresponding new[]
, but there is nothing in the standard that guarantees that.
So, it is possible, given a pointer which had not been previously allocated by new[]
, delete[]
ends up looking at something that really is not a consistent bookkeeping structure. Wires get crossed. A crash ensues.
Or, you might wish that delete[]
would say "hey, it looks like this pointer points to somewhere inside a region I allocated before. Let me go back and find the pointer I returned when I allocated that region and use that to look up the bookkeeping information" but, again, there is no such requirement in the standard:
For the second (array) form, expression must be a null pointer value or a pointer value previously obtained by an array form of new-expression. If expression is anything else, including if it's a pointer obtained by the non-array form of new-expression, the behavior is undefined. [emphasis mine]
In this case, you are lucky because you found out you did something wrong instantaneously.
PS: This is a hand-wavy explanation
(*someInts)++;
. – Coplindelete[]
expects a pointer that was obtained from a corresponding arraynew
. Incrementing a pointer obtained from arraynew
, then passing the resulting pointer todelete[]
, is invalid and causes UB. As they correctly pointed out,someInts++;
is the problem line. – Crescintint main() { int* ptr = new int[5]; delete ++ptr; }
Same crash for the same reason, the only difference is that it doesn't output1
first. – Crescintdelete []
a pointer that wasn't obtained bynew []
; see[expr.delete/2]
in the standard, where it mentions delete array. So, no, there really isn't any 'maybe' at all. Furthermore, if you assume that any given user's example code doesn't actually reflect their actual code, then you logically can't accept anything as an MCVE, because you can't guarantee that they just made it up. No offense. – Crescintnew
"here" because the example given doesn't actually need dynamic memory allocation. This indicates thatnew
was used specifically to demonstrate the problem, not that the MCVE shouldn't containnew
.] – Crescintnew[]
todelete[]
, albeit in a roundabout way. To quote: "Maybe you think that it's possible to delete only part of the allocated memory? Or maybe that calling the delete operator will work with any pointer that is pointing inside the allocated object (no matter where exactly)?" – Crescintdelete[]
. – Crescintnew[]
todelete[]
, indicating that it was indeed the exact issue with the code in question. Perhaps I'm not the one that didn't read closely? – Crescint