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_ptr
s 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 thethis
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.