I am trying to identify a nasty bug where an object spontaneously gets corrupted while being inside a map, and after some hours of debugging, I think I might not have fully grasped the idea of std::shared_ptr.
Here is the Context:
Inside a method, I declare a std::shared_ptr and initialize it to point to a clone of the current object (created by new). Then - after some modifications to the object - I call the same method on that pointer (recursively).
Inside the next recursion of the method, the decision is made to insert this object into a std::unordered_map (which is a class-attribute, so it is available on all recursion levels).
This is some pseudo-code to illustrate what I mean:
class A
{
...
void DoSomething(void); // the recursive function
A* Clone(void) const { return new A(this); } // the clone method
...
static std::unordered_map<std::shared_ptr<A>,int> myMap{};
};
void A::DoSomething(void)
{
...
if (condition) myMap.insert({this,5}); // in a deeper recursive call, condition is true
...
std::shared_ptr<A> pA(Clone()); // make a copy
pA->... // modify it
pA->DoSomething(); // here is the recursive call
...
}
Problem: Sometimes, the object behind the pointer inside the std::unordered_map is destroyed, and it seems like this happens when the original std::shared_ptr goes out of scope.
My (tentative) understanding: Calling a method of the object the std::shared_ptr points to does not increase the reference count - inside the called method, I have access to this, which is the ptr the std::shared_ptr points to, but what I do with this in there is not affecting the original std::shared_ptr.
To verify this, I added code to make an extra clone into an extra std::shared_ptr, right at the moment of insertion into the map, and then everything works fine (just slower, and uses double the memory, which is both an issue - class A has a lot of complex data).
Question: Is my understanding correct? If not, how would I call a method of a std::shared_ptr so that the this inside the method is still the 'std::shared_ptr'? Or is this not possible, and I have to use another design?
Regarding duplicates: Should we pass a shared_ptr by reference or by value? seems to point that way, but is about passing parameters by value or by reference, which is not a choice I have with the this pointer.