How serious is the new/delete operator mismatch error?
Solution 1:
It's undefined behavior serious (it could work, it could crash, it could do something else).
Solution 2:
At the first sight, calling delete
instead of delete[]
should not be very bad: you destroy the first object and you provoke some memory leak.
BUT: then, delete
(or delete[]
) calls free
to free the memory. And free
needs its originally allocated address, to free the memory correctly. Or, the thing is, while new
returns the original adress allocated by malloc, new[]
returns a different address.
Calling free on the address returned by new[]
provokes a crash (it frees memory chaotically).
See these very instructive links for better understanding:
http://blogs.msdn.com/b/oldnewthing/archive/2004/02/03/66660.aspx#66782
http://web.archive.org/web/20080703153358/http://taossa.com/index.php/2007/01/03/attacking-delete-and-delete-in-c
From these articles it is also obvious why calling delete[]
instead of delete is also a very bad idea.
So, to answer: yes, it is a very very serious error. It corrupts memory (after calling the destructor of the first object only).
Solution 3:
It is very serious. With new[]
, implementations typically store somewhere the number of allocated array elements, since they need to know how many of them will be destructed by delete[]
.
Compare allocation and deallocations of a single object with new
/delete
and new[]
/delete
: https://godbolt.org/z/GYTh7f7Y7. You can clearly see that the machine code in the latter case is much more complicated. Note that new[]
stores the number of elements (1) to the beginning of the allocated memory with mov QWORD PTR [rax], 1
. delete[]
then reads this number with mov rsi, QWORD PTR [rdi-8]
to be able to iterate over elements and call their destructors.
Ordinary new
does not store this number, so consequently, when you use new
together with delete[]
, delete[]
will read some unspecified number and apply destructors to unpredicted memory. This can create serious vulnerability problems.
The opposite new[]
plus delete
case is also very wrong. Ordinary new
expression typically returns a pointer that points exactly to the memory block internally allocated by operator new
(which usually calls malloc
). This pointer when passed to delete
expression is then internally passed as-is to the operator delete
deallocation function.
But the same does not hold for new[]
. Namely, new[]
does not return a pointer obtained internally by operator new
. Instead, it returns this pointer increased by 8 bytes (with GCC, but I think the same holds for Clang and MSVC on x86_64). See that lea r12, [rax+8]
in the linked assembly. In these 8 bytes, the number of allocated array elements is stored. Consequently, if you apply delete
to what you obtained with new[]
, delete
will pass to operator delete
a pointer that has not been allocated with operator new
, because it will not subtract those 8 bytes from it. This will finally likely cause some like heap corruption.