Home > Software engineering >  _CrtIsValidHeapPointer(block) when using std::shared_ptr
_CrtIsValidHeapPointer(block) when using std::shared_ptr

Time:12-16

I am trying to create and use a std::shared_ptr within a class function who's 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();
}

CodePudding user response:

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();
}

CodePudding user response:

With the code

std::shared_ptr<Containing_Class>(this)

you introduce a second *this owner, i.e. command is the owner of a shared pointer that controls cc life. That is the first issue. Yet another, following issue is that command is pointing to a stack object.

Usually *this is owned by someone and passing ownership to another owner never works.

The current code is impossible to fix due to lack of the code aim.

  • Related