2

Binding a method with an object pointer and deleting the object afterwards, the method is still callable.

struct A {
    void b(){std::cout << "SUHDU" << std::endl;}
};

int main(int argc, const char * argv[])
{
    A *a = new A;
    auto f1 = std::bind(&A::b, a);
    auto f2 = std::bind(&A::b, std::ref(a));

    f1();
    f2();

    delete a;
    f1(); // still outputs SUHDU
    f2(); // still outputs SUHDU
}

Why does std::bind behave this way and how does it do it?

Appleshell
  • 7,088
  • 6
  • 47
  • 96
  • 7
    This is undefined behaviour. It has nothing to do with `std::bind`, really. – chris Sep 15 '13 at 14:15
  • @chris So it's just un-reallocated memory. – Appleshell Sep 15 '13 at 14:16
  • [Similar question](http://stackoverflow.com/questions/18478262/c-why-i-can-access-member-functions-even-after-the-object-was-deleted) – chris Sep 15 '13 at 14:18
  • As it is undefined behavior it isn't guaranteed that you can make it fail but you could have the destructor of your `A` object set a pointer to null which used by `b()`: most likely this would cause a crash. For example, `struct A { std::ostream* out; A(): out(&std::cout) {} ~A() { out = 0; } void b() { *(this->out) << "hello\n"; } };`. Your example didn't really access anything from `A`, i.e., there is no reason the function needs to fail. – Dietmar Kühl Sep 15 '13 at 14:43

1 Answers1

5

It is undefined behaviour. It stores a copy of the argument, in your case the A* which is later on invalid. This hint also leads to the fix: To make your example legal, use std::shared_ptr:

struct A {
    void b(){std::cout << "SUHDU" << std::endl;}
};

int main(int argc, const char * argv[])
{
    auto a = std::make_shared<A>();
    auto f1 = std::bind(&A::b, a);

    f1();

    a.reset();

    f1(); // still outputs SUHDU
}

Of course, this will keep your object alive until f1 goes out of scope.

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180