Search code examples
c++intel-pin

Adding elements to global vector of vectors of structs


I have a global vector of vector of structs of this form:

vector<vector<stackEntry>> shadowStacksVector

where the idea is to have a vector<stackEntry> per thread.

In the thread start function I do the following:

vector<stackEntry> sstack;
shadowStacksVector.push_back(sstack);
tdata->shadowStack = &(shadowStacksVector.back());

where tdata is a struct containing the thread local storage. What I would like to do is to have, for each thread, a reference to the vector of stack entries, so that each thread can add or remove elements to its own stack. Conceptually I believe that push_back does a copy of the element so I thought that this should have worked. However, when I try to add/remove elements from tdata->shadowStack my program crashes.

On the contary, if I replace the vector of vectors with an array like this:

vector<stackEntry> shadowStacksVector[256]

everything works fine.


Solution

  • Containers are not thread safe, you need to create thread-safe sections of code to work with them in several threads. Use std::mutex or std::atomic to create thread-safe sections of code.

    Neither std::vector nor std::list is thread-safe. Your std::vector fails probably because when you push_back new value its allocated memory can do reallocate and all elements can move in other part of memory, so your old pointers can point on old broken data. If you will use shadowStacksVector->reserve(MAX_INTERNAL_VECTORS_COUNT) at start vector's memory won't be reallocating when you do push_back, it guarantees that std::vector reserved memory for MAX_INTERNAL_VECTORS_COUNT and next reallocate can happen after you will push_back MAX_INTERNAL_VECTORS_COUNT+1 element.

    std::list don't need to reallocate all his elements, because its elements can store in different parts of memory, it allocates memory for each element every time you do push_back, so old pointers are point on the same place of memory.