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.