I checked the following code in C++ with valgrind
with --leak-check=full
and it says no memory leak. Why is that?
char *p = new char[256];
delete p;
new[]
should be matched by delete[]
as far as I know.
I checked the following code in C++ with valgrind
with --leak-check=full
and it says no memory leak. Why is that?
char *p = new char[256];
delete p;
new[]
should be matched by delete[]
as far as I know.
Although it's undefined behaviour as @KillianDS says, the difference probably relates to the fact that both delete
and delete[]
free the underlying memory. The point of delete[]
is that the destructors for each object in the array are called before the memory is freed. Since char
is a POD and doesn't have a destructor, there isn't any effective difference between the two in this case.
You definitely shouldn't rely on it, however.
delete
and delete[]
will be equal only if the p
points to basic data types, such as char or int.
If p
points to an object array, the result will be different. Try the code below:
class T {
public:
T() { cout << "constructor" << endl; }
~T() { cout << "destructor" << endl; }
};
int main()
{
const int NUM = 3;
T* p1 = new T[NUM];
cout << p1 << endl;
// delete[] p1;
delete p1;
T* p2 = new T[NUM];
cout << p2 << endl;
delete[] p2;
}
By using delete[]
all the destructors of T in the array will be invoked. By using delete
only p[0]
's destructor will be invoked.
When I try this, valgrind reports:
==22707== Mismatched free() / delete / delete []
==22707== at 0x4C2B59C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22707== by 0x40066D: main (in /home/andrew/stackoverflow/memtest)
==22707== Address 0x5a1a040 is 0 bytes inside a block of size 256 alloc'd
==22707== at 0x4C2C037: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22707== by 0x40065D: main (in /home/andrew/stackoverflow/memtest)
It's not really a memory leak, but valgrind does notice the problem.
Because it's undefined behavior. In your case, delete
may do the work of delete []
in your compiler, but it may not work on another machine.
This is undefined behavior, so we can not reason about its behavior. If we look at the draft C++ standard section 3.7.4.2
Deallocation functions, paragraph 3 says (emphasis mine):
[...] Otherwise, the behavior is undefined if the value supplied to operator delete(void*) in the standard library is not one of the values returned by a previous invocation of either operator new(std::size_t) or operator new(std::size_t, conststd::nothrow_t&) in the standard library, and the behavior is undefined if the value supplied to operator delete[] (void*) in the standard library is not one of the values returned by a previous invocation of either operator new[] (std::size_t) or operator new[] (std::size_t, const std::nothrow_t&) in the standard library.
The actual details are going to be implementation-defined behavior and could vary greatly.
The difference between delete
and delete []
is that the compiler adds code to call the destructor for the deleting objects. Say something like this:
class A
{
int a;
public:
...
~A() { cout<<"D'tor"; }
};
a=new A[23];
delete [] a;
This delete [] a;
is transformed to something like,
for (int i=0; i<23; i++)
{
a[i].A::~A();
}
std::delete a;
So, for your case since it is an built in datatype there is no destructor to call. So, it transformed as,
std::delete a;
which intern calls the free()
to deallocate the memory. That's the reason that you are not getting any leak. Since memory allocated is completely deallocated using free()
in g++.
But best practice is that you have to use delete []
version if you use new []
.