I would like to know why in the following code the first delete won't free the memory:
#include <list>
#include <stdio.h>
struct abc {
long a;
abc() {
puts("const");
}
~abc() {
puts("desc");
}
};
int main() {
std::list<abc*> test;
abc* pA = new abc;
printf("pA: 0x%lX\n", (unsigned long int)pA);
test.push_back(pA);
abc* pB = test.back();
printf("pB: 0x%lX\n", (unsigned long int)pB);
delete pB; // just ~abc()
test.pop_back();
delete pA; // ~abc() and free (works)
puts("before double-free");
delete pA; // ~abc() and second free (crash)
return 0;
}
Output is:
const
pA: 0x93D8008
pB: 0x93D8008
desc
desc
before double-free
desc
*** glibc detected *** ./test: double free or corruption (fasttop): 0x093d8008 ***
...
I tried it with free()
also but same behavior.
delete pA; // ~abc() and free (works)
puts("before double-free");
delete pA; // ~abc() and second free (crash)
These delete
statements are not needed once you write delete pB
. You've a misconception that delete pB
only calls the destructor. No, it calls the destructor and also deallocates the memory.
Also, since you've already written delete pB
, the next two further delete
expressions invoke undefined behavior , which means anything can happen : the program may or may not crash!
Have a look at these topics:
Your first delete renders the pointer to invalid state. So use of that pointer now leads to undefined behaviour.
int* p = new int;
delete p;
delete p; //undefined behaviour
This is guaranteed to be fine by the standard (as pointed out in the first comment):
int* p = new int;
delete p;
p = 0;
delete p; //fine
First, you can't free
memory allocated with new
, you have to use delete
.
Secondly, just because glibc doesn't detect the double free immediately, how do you know delete pB;
isn't freeing it? That's what delete
does, and from your own logging you're passing the same address to delete
each time.
Thirdly: what are you actually trying to accomplish?
It's just an indiosyncracy of your compiler/platform that you had to call delete
twice on pA
before glibc
complained ... for instance, on my current platform, which is OSX 10.6.8 with gcc
version i686-apple-darwin10-gcc-4.2.1, I get the following output:
const
pA: 0x100100080
pB: 0x100100080
desc
desc
test(14410) malloc: *** error for object 0x100100080: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap
So you can see the first call to delete
on pA
, which by the standard results in undefined behavior since you didn't set the pointer to NULL
or 0
, did get caught as an attempt to deallocate already deallocated memory by the C++ run-time on my platform.
Since the results of the double-delete are "undefined behavior", it's really up to the implementation and platform on what happens.
You may be able to detect allocation/deallocation memory errors quicker if you use the link against the glibc memory consistency checker by compiling with the -lmcheck
flag.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.