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.