Multiple C++ deletion of a memory pointed by multiple objects
-
30-09-2019 - |
Pergunta
Another C++ pointer deletion question is in the following example:
class Foo {
public:
int *p;
~Foo() {
delete p; p = NULL;
}
};
Foo *f1 = new Foo();
Foo *f2 = new Foo();
f1->p = new int(1);
f2->p = f1->p;
delete f2; // ok
delete f1; // no error?
Why I did not get error when calling "delete f1"? didn't I delete the same address (*p) twice?
If I directly delete the pointers in the last 2 lines of code, I will get error.
delete f2->p; // ok
delete f1->p; // error!! *** glibc detected *** double free or corruption (fasttop) ***
Solução
It is a VERY bad thing to do. However C++ won't necessarily do anything here. It is "un-defined" behaviour. That doesn't mean it will crash but it will, most probably, cause bad shit (tm) to happen.
Edit: Furthermore in your 2nd example the fact it crashes is just a part of "undefined" behaviour. It is undefined as to what the reaction will be.
Outras dicas
Why I did not get error when calling "delete f1"? didn't I delete the same address (*p) twice?
Yes you did delete that object twice.
However, the outcome of that is Undefined Behavior. That could result in the run-time system catching the error and popping up a message, but it could just as well result in your HD getting formatted, nasty Nasal Demons chasing you around the office to the delight of your fellow-workers, or you or your girlfriend getting pregnant. Or then it might also appear to "work", whatever that means in this case.
Trust me, you don't want to do that.
Take a look at boost::shared_ptr
: it allows you to deal with pointers in an elegant way, without having to care too much about their deletion.
class Foo {
public:
boost::shared_ptr<int> p;
};
Foo *f1 = new Foo();
Foo *f2 = new Foo();
f1->p.reset(new int(1));
f2->p = f1->p;
delete f2; // ok
delete f1; // no error and its guaranteed !
If you don't want to use boost
, some compilers already provide std::tr1::shared_ptr
which has similar semantics.
If you want to use multiple pointers to the same memory, encapsulate them in boost::shared_ptr
, which will ensure that the underlying memory is not delete-d until the last reference to it goes out of scope.
#include <boost/shared_ptr.hpp>
class Foo {
public:
boost::shared_ptr<int> p;
~Foo() {
p.reset();
}
};
Foo *f1 = new Foo();
Foo *f2 = new Foo();
f1->p.reset(new int(1));
f2->p = f1->p;
delete f2; // ok
delete f1; // no error
Of course double deletes are undefined behavior. It is also likely to change if between debug and release builds. Others have pointed out to you the goodness of boost::shared_ptr
and such.
However, it is useful to also mention how you can find these kind of bugs reliably:
Run your program in valgrind.
On Windows, purify is the older, commercial counterpart to valgrind.