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

            Bug ID: 125565
           Summary: std::enable_shared_from_this::_M_weak_this not reset
                    before calling deleter
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: boris at kolpackov dot net
  Target Milestone: ---

The following test illustrates the problem:

#include <memory>
#include <vector>
#include <cassert>

struct connection: std::enable_shared_from_this<connection> {};

std::vector<std::unique_ptr<connection>> connection_pool;

int main ()
{
  std::shared_ptr<connection> c (
    new connection,
    [] (connection* c)
    {
      // Verify the weak pointer stored in enable_shared_from_this
      // is empty and thus not preventing the control block from
      // being freed.
      //
      std::weak_ptr<connection> w (c->weak_from_this ()), e;
      assert (!w.owner_before (e) && !e.owner_before (w));

      connection_pool.push_back (std::unique_ptr<connection> (c));
    });

  c.reset (); // Return connection to the pool.
}

In other words, when using an object with std::enable_shared_from_this and a
custom deleter, the object passed to the deleter still has its weak_ptr (stored
in enable_shared_from_this) pointing to the original control block. If the
object is not destroyed (and is instead recycled, as in the example), then the
control block will not be freed until the weak_ptr is reset with a new
shared_ptr.

Feels like calling _M_weak_this.reset() before calling the deleter would be a
straightforward fix.

As far as I can see, there is no way to work around the issue from the user
code.

Reply via email to