Search code examples
c++multithreadingc++11stdthread

How does this simple multithread code lead to memory corruption?


The following code reliably produces a segfault.

#include <vector>
#include <thread>

class Class {
public:
    Class(const int integer)
        : cinteger(integer), carray(std::array<int, 1>{0})
    {}

   const int operator()() 
   {
    carray[cinteger] = 0;
        return cinteger;
    }
    
private:
    int cinteger;
    std::array<int, 1> carray;
};

class Worker{
    public:
        Worker( Class iClass): 
            wClass(iClass),
            thread(&Worker::thread_main, this)
            {}
        
        void join(){thread.join();}     

    private:
        Class wClass;
        std::thread thread;
        void thread_main(){
            for(int i = 0; i < 50000; i++)
            wClass();
        }
};

int main()
{
    std::vector<Worker> Workers;
    for(int i = 0; i < 4; i++)
        Workers.emplace_back(Class(0));
    for(int i = 0; i < 4; i++)
        Workers[i].join();
    return 0;
}

For some reason, I do not understand, the cinteger variable of Class seems to get changed unexpectedly. This problem arises every time I run the code. It does not arise if I only generate 3 workers. Also, at 1000 iterations in the Worker class the problem does not appear.

TBH I am a bit out of ideas of where this problem could come from.


Solution

  • This is quite simple really. In the thread you reference this, however as you perform emplace_back in the vector, it'll eventually lead to resize of the vector and move the objects to a different place in memory. Invalidating previous instances. Which leads to this being invalid and corrupted inside the thread_main() member function.