Search code examples
c++thisshared-ptr

shared_from_this() crashes in specific case


Option 1 crashes the app on shared_from_this() with bad_weak_ptr, while option 2 works fine, why? the only difference i see is where the clone is being created - in the Clone() function or in line with creating shared_ptr for the clone, in both cases the shared_from_this requirement of already having shared_ptr with ownership of this when using shared_from_this() is met

class Base
{
public:
    virtual Base* Clone() = 0;
};

class Derived : public Base, public std::enable_shared_from_this<Derived>
{
public:
    Base* Clone() override
    {
        return new Derived(*this);
    }
    void test()
    {
        std::shared_ptr<Derived> ptr = shared_from_this();
    }
};

int main()
{
    std::shared_ptr<Base> obj = std::make_shared<Derived>();
    //std::shared_ptr<Base> clone = std::shared_ptr<Base>(obj->Clone()); // option 1
    std::shared_ptr<Base> clone = std::shared_ptr<Base>(new Derived(*std::static_pointer_cast<Derived>(obj))); // option 2
    std::shared_ptr<Derived> derived = std::static_pointer_cast<Derived>(clone);
    derived->test();

    return 0;
}

Solution

  • You can't new an object that derives from enable_shared_from_this and for it to safely work since the new object doesn't actually have a shared_ptr container.

    Instead of this:

    Base* Clone() override
    {
        return new Derived(*this);
    }
    

    This:

    shared_ptr<Base> Clone() override
    {
        return make_shared<Derived>(*this);
    }
    

    Similar adjustment in the base class declaration:

    virtual shared_ptr<Base> Clone() = 0;