Tuesday, July 1, 2008

"delete []" versus just "delete" in C++

This week I was asked for the second time to "fix" a bug in my code and use "delete []" on arrays instead of "delete". I did an informal survey and all of the people I asked told me using plain "delete" on arrays is wrong.

As I remembered that it is ok, I decided to do some experiments.

I wrote this code and compiled it in VS2008:

#include "stdafx.h"
TCHAR * buf = NULL;
int * intbuf = NULL;

class Foo
int x;
// ~Foo() { x = 2; }
Foo * fooBuf = NULL;

int _tmain(int argc, _TCHAR* argv[])
delete buf;
delete [] buf;
delete intbuf;
delete [] intbuf;
delete fooBuf;
delete [] fooBuf;
return 0;

Now let us check the disassembly:

delete buf;
003E1000 mov eax,dword ptr [buf (3E3370h)]
003E1005 push eax
003E1006 call operator delete (3E105Ch)
delete [] buf;
003E100B mov eax,dword ptr [buf (3E3370h)]
003E1011 push eax
003E1012 call operator delete (3E105Ch)

delete intbuf;
003E1017 mov eax,dword ptr [intbuf (3E3374h)]
003E101D push eax
003E101E call operator delete (3E105Ch)
delete [] intbuf;
003E1023 mov eax,dword ptr [intbuf (3E3374h)]
003E1028 push eax
003E1029 call operator delete (3E105Ch)

delete fooBuf;
003E102E mov eax,dword ptr [fooBuf (3E3378h)]
003E1034 push eax
003E1035 call operator delete (3E105Ch)
delete [] fooBuf;
003E103A mov eax,dword ptr [fooBuf (3E3378h)]
003E1040 push eax
003E1041 call operator delete (3E105Ch)

003E1046 add esp,18h

return 0;

All identical.

Now if you uncomment the destructor interesting things start to happen on the last two deletes:

delete fooBuf;
002C103E mov eax,dword ptr [fooBuf (2C3378h)]
002C1043 add esp,10h
002C1046 test eax,eax
002C1048 je wmain+71h (2C1081h)
002C104A push eax
002C104B mov dword ptr [eax],2
002C1051 call operator delete (2C1094h)
002C1056 mov eax,dword ptr [fooBuf (2C3378h)]
002C105B add esp,4

delete [] fooBuf;
002C105E test eax,eax
002C1060 je wmain+71h (2C1081h)
002C1062 mov ecx,dword ptr [eax-4]
002C1065 push esi
002C1066 lea esi,[eax-4]
002C1069 push offset Foo::~Foo (2C1000h)
002C106E push ecx
002C106F push 4
002C1071 push eax
002C1072 call `eh vector destructor iterator' (2C10F8h)
002C1077 push esi
002C1078 call operator delete (2C1094h)
002C107D add esp,4
002C1080 pop esi

The calls are very different because in second case it goes through the array and destructs individual elements, while in the first just deletes the memory.

“delete” and “delete []” are equivalent unless the array contains objects and that objects have a destructor.

This said it is still probably good idea to use "delete []" for the clarity alone.