C++: Error passing address of own struct as parameter to pthread_create: What overwrites my data?

StackOverflow https://stackoverflow.com/questions/23308161

  •  09-07-2023
  •  | 
  •  

Question

I have a nasty error using pthreads in C/C++. The attached code can be used to reproduce it:

#include <iostream>
#include <vector>
#include <random>
#include <pthread.h>

using namespace std;

const int NUM_THREADS = 2;

//These structs don't serve a specific purpose,
//but are necessary to reproduce the error
struct my_struct {
    float a;
    float x;
    float y;
    float z;
};

struct my_param {
    struct my_struct my_struct_obj;
    vector<struct my_struct>* my_struct_vec;
    float t;
};

void* thread_function(void* arg){
    struct my_param param = *(struct my_param*)(arg);
    printf("Param values for (x, y, z): (%f, %f, %f)\n",
            param.my_struct_obj.x, param.my_struct_obj.y, param.my_struct_obj.z);
    return NULL;
}

void run_multithread_function(vector<struct my_struct> &my_struct_vec,
        struct my_struct obj, float a){

    void* exit_status[NUM_THREADS];
    pthread_t thread_IDs[NUM_THREADS];

    //holds the parameter for the functions assigned
    vector<struct my_param> thread_params;

    //create the threads
    for(unsigned int i = 0; i < NUM_THREADS; i++){
        struct my_param parameter;
        parameter.my_struct_obj = obj;
        parameter.my_struct_vec = NULL;
        thread_params.push_back(parameter);
        pthread_create(&thread_IDs[i], NULL, thread_function, &thread_params[i]);
    }

    //join the threads
    for(unsigned int i = 0; i < NUM_THREADS; i++){
        pthread_join(thread_IDs[i], &exit_status[i]);
    }
}
int main() {
    vector<struct my_struct> mass_objects;
    struct my_struct my_obj;
    my_obj.x = 1;
    my_obj.y = 1;
    my_obj.z = 1;
    float a = 8;
    run_multithread_function(mass_objects, my_obj, a);
}

The problem is that the variable passed to the thread seems to be somelike overwritten, as the snippets outputs

Param values for (x, y, z): (0.000000, 1.000000, 1.000000) Param values for (x, y, z): (1.000000, 1.000000, 1.000000)

instead of all 1.000000. All the snippet does is creating two new threads, and passing each of them the function

void* thread_function(void* arg)

with the argument

&thread_params[i]

which is the address of an item in a vector of structs. I was unable to find the source of the mentioned error and would appreciate any hints. What I have found out, it that reordering the variables in my struct to

struct my_param {
    vector<struct my_struct>* my_struct_vec;
    struct my_struct my_struct_obj;
    float t;
};

somehow seems to solve the problem. Furthermore, if the function thread_function is called directly (without creating a thread), the error disappears as well. Therefore, I assume that I make some pthread-related mistake. Any suggestions?

Was it helpful?

Solution

There are no guarantees with respect to the initial allocation size of thread_params, so as you push into the vector and simultaneously pass thread_params[i] to the threads you cannot really say that reallocation won't occur on the second push_back.

Push the values into the vector in a separate loop, or set an initial capacity:

vector<struct my_param> thread_params;
thread_params.reserve(2);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top