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) ***
Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top