Search code examples
c++pointersvectorscopeshared-ptr

shared_ptr in vector trouble - iterating and losing scope - getting corrupted data


I'm not new to C++ but I do mostly work in C# and other managed languages usually so I'm not that well versed in shared pointers etc.

I basically have a 3-dimensional map of shared_ptrs to objects of a custom class (for 3d purposes).

These shared_ptrs live inside the map and are referenced all over the project, so far so good. For a specific piece of functionality I store some of these shared_ptrs in a vector to be iterated over later in the code but this is where things seem to break down.

Say I have 100 of these objects with their pointers stored in the 3d map and 3 of them are added to the vector because they have special properties for functionality. When I'm traversing the vector I call functions on these 3 objects. This all works fine until the for loop (for the iteration) hits it's second run on element [1] of the vector, at this point element [0] is full of corrupted data (but element[1] needs to access element[0] to perform one of the functions) and this is where I get an error.

As I said, I'm not that well versed in shared_ptrs but I thought that the data wouldn't be corrupted because the actual object is created in the creation of the 3-dimensional map - also, the vector hasn't gone out of scope yet because I am only in the 2nd run through the for loop (with 3 objects and so 3 iterations).

I know I must be doing something wrong but I have no idea how to debug this further - basically when I step through the code and it comes to the 2nd run of the for loop, if I look at element [0]'s shared_ptr in the vector (using VS) it is all corrupted.

Here is the loop of the code so you can see. The vector is created in the constructor of the class this code is in and the map (where the shared_ptrs and objects are created) is in the main class of the application. Also, getAdjacent takes objA and objB as pointers and so "fills" objB with the data of the adjacent object to objA:

for(vector<shared_ptr<ObjectClass>>::iterator iterator = objects.begin(); iterator != objects.end(); iterator++)
{
    shared_ptr<ObjectClass> objA = (shared_ptr<ObjectClass>) iterator->get();

    shared_ptr<ObjectClass> objB;

    m_3DMap->getAdjacent(objA, objB);

    objA->move(objB);
}

Could it be something to do with the cast I perform on iterator->get()? I couldn't see any other way to do it because if I don't have that cast there VS says that it can't convert from ObjectClass* to shared_ptr which is confusiong to me too because I thought I have a vector of shared_ptrs?..

Thanks for your time and it would be great if anyone could help.


Solution

  • Okay I found the problem I had.

    It was in part to do with what Balog Pal said about putting the shared_ptrs in a vector even though they live in a map so I changed this so that the vector held pointers to the shared_ptrs. Although this may still be bad practice, it got around the issue - especially as the vector was local and lost scope after the function exited.

    The original vector approach was implemented as I was getting a dereference on my map iterator somewhere in the function and so I decide to leave all map manipulation outside the iterating (hence storing the 'special' objects in the vector to be iterated over later).

    I have now changed the implementation to get rid of this inefficiency as my manipulation functions now return a new map iterator and thus negating the problem.

    It would have been nice if the error message was somewhat more helpful that it was because it took me some time to realize the iterator became invalidated because I had an insert() buried in one of the functions that was called on the 'special' objects.

    Although this answer doesn't really answer the exact question I asked, it answers the problem as a whole and why I designed the function in the way I did in the question.

    Thanks for the help Balog and itwasntpete for the answers and comments.