Search code examples
c++shared-ptr

_CrtIsValidHeapPointer(block) when using std::shared_ptr


I am trying to create and use a std::shared_ptr within a class function whose constructor takes in a std::shared_ptr private data member (of the same class) and another std::shared_ptr created with a raw pointer to the class object (this).

Whenever I call the function that creates the std::shared_ptr (foo), I get a _CrtIsValidHeapPointer(block) assertion. I'm assuming it has something to do with the way in which the shared_ptr is being deleted, but I can't seem to figure it out, and I've searched all over the Internet. Maybe I'm not fully understanding how shared_ptrs work.

Is it not acceptable to create a shared_ptr using the this pointer, or a pre-existing shared_ptr data member?

class Containing_Class;

class Some_Class
{
};

class Set_Value_Command
{
public: 
    Set_Value_Command(std::shared_ptr<Some_Class> ptr1, std::shared_ptr<Containing_Class> ptr2)
        : _ptr1(ptr1), _ptr2(ptr2) 
    {}
private:
    std::shared_ptr<Some_Class> _ptr1;
    std::shared_ptr<Containing_Class> _ptr2;
};

class Containing_Class
{
public:
    Containing_Class(std::shared_ptr<Some_Class> psc)
        : _psc(psc)
    {}

    void foo()
    {
        std::shared_ptr<Set_Value_Command> command = std::make_shared<Set_Value_Command>(_psc, std::shared_ptr<Containing_Class>(this));
    }
private:
    std::shared_ptr<Some_Class> _psc;
};

Here is the main() function. When foo() is called, the assertion happens:

int main()
{
    std::shared_ptr<Some_Class> some_class = std::make_shared<Some_Class>();
    Containing_Class cc(some_class);
    cc.foo();
}

Solution

  • Is it not acceptable to create a shared_ptr using the this pointer

    Not by itself, no. And doing so in your example is very bad. Your Containing_Class object is being created in automatic memory of main()'s local stack frame, and thus will be destroyed automatically when it goes out of scope when main() exits. But creating a shared_ptr from this inside of the Containing_Class object will assign ownership of this to the shared_ptr, which will then try to delete this when there are no more shared_ptr references to this. delete'ing an object that was not created with new to begin with is undefined behavior, and is why you are crashing with an error about an invalid heap pointer.

    In order to allow shared_ptr to refer to this, Containing_Class would need to derive from std::enable_shared_from_this, and this would have to point at an object that is created dynamically and owned by a shared_ptr. Only then can Containing_Class call its inherited shared_from_this() method to get a shared_ptr to itself.

    For example:

    class Containing_Class;
    
    class Some_Class
    {
    };
    
    class Set_Value_Command
    {
    public: 
        Set_Value_Command(std::shared_ptr<Some_Class> ptr1, std::shared_ptr<Containing_Class> ptr2)
            : _ptr1(ptr1), _ptr2(ptr2) 
        {}
    private:
        std::shared_ptr<Some_Class> _ptr1;
        std::shared_ptr<Containing_Class> _ptr2;
    };
    
    class Containing_Class : public std::enable_shared_from_this<Containing_Class>
    {
    public:
        Containing_Class(std::shared_ptr<Some_Class> psc)
            : _psc(psc)
        {}
    
        void foo()
        {
            std::shared_ptr<Set_Value_Command> command = std::make_shared<Set_Value_Command>(_psc, shared_from_this());
        }
    
    private:
        std::shared_ptr<Some_Class> _psc;
    };
    
    int main()
    {
        auto some_class = std::make_shared<Some_Class>();
        auto cc = std::make_shared<Containing_Class>(some_class);
        cc->foo();
    }