Is delete[] equal to delete?
It will usually not leak because in case of POD destructors are trivial and there's no need for invoking them so delete
just deallocates memory occupied by the array. Memory deallocation requires just a pointer value so it will be returned to the heap. The array accopies a contiguous block of memory and so the deallocation can be sucessful just as if it was a deallocation of a single element.
But don't rely on this since it is undefined behaviour. Maybe it works allright, maybe something horrible happens, works on this compiler, doesn't work on another and many people thank you for planting an error.
See this answer for details.
delete : calls the appropriate destructor only for the element pointed to (if needed), then frees the memory chunk
delete[] : calls the appropriate destructors for each element in its array (if needed), then frees the memory chunk
Just an illustration of some "undefined" behaviors on certain OSes and compilers. Hope it could be helpful for people to debug their code.
Test 1
#include <iostream>
using namespace std;
int main()
{
int *p = new int[5];
cout << "pass" << endl;
delete p;
return 0;
}
Test 2
#include <iostream>
using namespace std;
int main()
{
int *p = new int;
cout << "pass" << endl;
delete[] p;
return 0;
}
Test 3
#include <iostream>
using namespace std;
struct C {
C() { cout << "construct" << endl; }
~C() { cout << "destroy" << endl; }
};
int main()
{
C *p = new C[5];
cout << "pass" << endl;
delete p;
return 0;
}
Test 4
#include <iostream>
using namespace std;
struct C {
C() { cout << "construct" << endl; }
~C() { cout << "destroy" << endl; }
};
int main()
{
C *p = new C;
cout << "pass" << endl;
delete[] p;
return 0;
}
- Windows 7 x86, msvc 2010. Compile with default options, i.e. exception handler is enabled.
Test 1
pass
Test 2
pass
Test 3
construct
construct
construct
construct
construct
pass
destroy
# Then, pop up crash msg
Test 4
construct
pass
destroy
destroy
destroy
destroy
destroy
destroy
destroy
... # It never stop until CTRL+C
- Mac OS X 10.8.5, llvm-gcc 4.2 or gcc-4.8 generate the same output
Test 1
pass
Test 2
pass
Test 3
construct
construct
construct
construct
construct
pass
destroy
a.out(71111) malloc: *** error for object 0x7f99c94000e8: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
zsh: abort ./a.out
Test 4
construct
pass
a.out(71035) malloc: *** error for object 0x7f83c14000d8: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
zsh: abort ./a.out
- Ubuntu 12.04, AMD64, gcc 4.7
Test 1
pass
Test 2
pass
Test 3
construct
construct
construct
construct
construct
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x0000000001f10018 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7fe81d878b96]
./a.out[0x400a5b]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fe81d81b76d]
./a.out[0x4008d9]
======= Memory map: ========
....
zsh: abort (core dumped) ./a.out
Test 4
construct
destroy
destroy
destroy
destroy
destroy
destroy
destroy
destroy
...
destroy
destroy
*** glibc detected *** ./a.out: free(): invalid pointer: 0x00000000016f6008 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7fa9001fab96]
./a.out[0x400a18]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fa90019d76d]
./a.out[0x4008d9]
======= Memory map: ========
...
zsh: abort (core dumped) ./a.out
Whether this leads to a memory leak, wipes your hard disk, gets you pregnant, makes nasty Nasal Demons chasing you around your apartment, or lets everything work fine with no apparent problems, is undefined. It might be this way with one compiler, and change with another, change with a new compiler version, with each new compilation, with the moon phases, your mood, or depending on the number of neutrinos that passed through the processor on the last sunny afternoon. Or it might not.
All that, and an infinite number of other possibilities are put into one term: Undefined behavior:
Just stay away from it.