Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a std::function's target callable legally destroy the std::function during execution?

In comments under another question, it was stated that a common mistake is to:

invoke std::function when calling it leads to destruction of object which holds it

While clearly a "dangerous" thing to do that would be avoided in robust code, is it actually wrong? I cannot find any wording in the standard that ensures:

  • A std::function must not be destroyed by its target callable
  • A std::function's lifetime must not end during execution of its target callable
  • The lifetime of a functor in general must not end during its execution

To my knowledge, it is legal and well-defined (though in poor taste) to do things like the following:

struct Foo
{
   void baz()
   {
      delete this;
      // Just don't use any members after this point
   }
};

int main()
{
   Foo* foo = new Foo();
   foo->baz();
}

This suggests that, in the absence of any overriding restrictions, none of which I can find, the following would also be technically well-defined:

#include <functional>

struct Bar
{
   std::function<void()> func;
};

int main()
{
   Bar* bar = new Bar();
   bar->func = [&]() { delete bar; };
   bar->func();
}

Is this not the case? If not, which wording prohibits it?

(For bonus points, it would be interesting if this has changed since previous standards.)

like image 560
Asteroids With Wings Avatar asked Jul 16 '20 17:07

Asteroids With Wings


1 Answers

[res.on.objects]/2:

If an object of a standard library type is accessed, and the beginning of the object's lifetime does not happen before the access, or the access does not happen before the end of the object's lifetime, the behavior is undefined unless otherwise specified. [ Note: This applies even to objects such as mutexes intended for thread synchronization. — end note ]

As far as the library is concerned, a member function can access the object until it returns. It follows that destroying the object in the middle of such a call is undefined unless permission is explicitly granted.

like image 106
T.C. Avatar answered Sep 30 '22 01:09

T.C.