Nicholas Dry Nicholas Dry - 25 days ago 15
C Question

Inconsistent values when printing from a thread

I am in the process of learning about thread programming and have been running a test exercise to see how it works when you call a function from pthread_create, however, I am having weird results when doing it. Here is my code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

pthread_t *threads;

typedef struct _file {
int num1;
int num2;
} file;

void thread_run(void *thing) {
file *fp = thing;

printf("num1: %d num2: %d\n", fp->num1, fp->num2);

}

int main(int argc, char **argv) {

threads = (pthread_t *)malloc(atoi(argv[1]));

file *args = malloc(sizeof(file));
args->num1 = 0;
args->num2 = 0;
int i;
for (i = 0; i < atoi(argv[1]); i++) {
args->num1 = i;
args->num2 = i + 1;
pthread_create(&threads[i], NULL, (void *)thread_run, (void *)&args); // the (void *) cast is necessary on my linux distro
}

for (i = 0; i < atoi(argv[1]); i++) {
pthread_join(threads[i], NULL);
}

return 0;
}


What I am attempting to have here is when I create the threads in the for loop, I store them all in my *threads pointer.

Then I call the method thread_run with a struct parameter which contains two integer values that I am printing out.

To my knowledge, the expected output of this program when run with ./a.out 3 should be:

num1: 0 num2: 1
num1: 1 num2: 2
num1: 2 num2: 3


However, the output I am getting varies each time but is usually consistent with something like:

num1: 34185264 num2: 0
num1: 34185264 num2: 0
num1: 34185264 num2: 0


I have noticed a few questions with a similar topic but none of the other users seem to be having the issue I have described.

Answer

Every thread has a pointer to the exact same struct. Therefore, they will print the same values. You should malloc() a new struct for each thread inside the for loop.

Also, args is declared as file *args. Note that this is already a pointer, so you should pass it directly rather than its address:

pthread_create(&threads[i], NULL, (void *)thread_run, (void *)args);