https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92200

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |INVALID

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
You create a cycle in the shared_ptr ownership, so the reference count never
goes to zero and never destroys the object.

a->tfut has a reference to the shared state created by std::async, and that
shared state has a reference to a. That means the reference count equals two:

  auto a = make_shared<A>();
  a->start_async();
  std::cout << "reference count: " << a.use_count() << '\n';
  a->tfut.wait();
  std::cout << "reference count: " << a.use_count() << '\n';
  a.reset();

This prints:

Constructing this 0x7fd710000b30
Start async this 0x7fd710000b30
reference count: 2
reference count: 2
Constructing this 0x7fd710001170
Start thread this 0x7fd710001170
Destroying this 0x7fd710001170

When you do a.reset() the reference count goes to one, and so the object is
never destroyed.

To break this cycle you need to use get() not wait(), so that the future
releases its reference on the shared state:

  auto a = make_shared<A>();
  a->start_async();
  std::cout << "reference count: " << a.use_count() << '\n';
  a->tfut.get();
  std::cout << "reference count: " << a.use_count() << '\n';
  a.reset();

Now it prints:

Constructing this 0x7fece0000b30
Start async this 0x7fece0000b30
reference count: 2
reference count: 1
Destroying this 0x7fece0000b30
Constructing this 0x7fece0000b30
Start thread this 0x7fece0000b30
Destroying this 0x7fece0000b30


So there is no bug in shared_ptr.

Reply via email to