Reputation: 51
so I was doing C programming homework and I came across a weird behaviour of the threads :
I gave a value to a thread and it gives it back into a pthread_exit()
function, then I add all returned values in the main function. The problem is that only the first value is completely wrong which means that my transtyping is right but there's a memory problem I haven't managed to solve even with help.
Here's the code :
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void * fonction_thread(void * arg);
long s = 0; //int to sum on
int main (int argc, char* argv[])
{
int N,i ; //N is the number of threads created
void* ret ; //returned value
N= atoi(argv[1]);
s=0;
for(i=1; i<N+1; i++){
//creation of the threads
pthread_t thr;
if (pthread_create(&thr, NULL, fonction_thread, &i) != 0) {
fprintf(stderr, "Erreur dans pthread_create\n");
exit(EXIT_FAILURE);
}
//recovering the value
pthread_join(thr, &ret);
printf("retour : %d\n\n", *((int*)ret)); //transtyping void* to int* before derefencement
s+= *((int*)ret);
}
printf("%ld\n", s);
}
//thread handler
void * fonction_thread(void * arg)
{
int n;
n = *((int *)arg); //recovering the value given by the main
printf("thread numéro %d créé\n", n);
pthread_exit((void*) &n); //casting then returning value
}
and here is the console view : console screeshot
Upvotes: 0
Views: 110
Reputation: 409166
One major problem is that you return a pointer to the local variable n
.
As soon as fonction_thread
exits, the life-time of all local variables ends, and any pointer to them becomes invalid.
For something like this it's considered okay (barely) to cast values to pointers and back again, which means you could do something like this to return the value:
return (void *) (intptr_t) n; // Or use pthread_exit((void *) (intptr_t) n)
Then when you receive the "pointer" you do the opposite cast:
int n = (int) (intptr_t) ret;
Note that you need to pass the value of i
to the thread the same way. Not because of life-time issues, but because all threads will have the exact same pointer, and there will be a data-race to get the value which means multiple threads could seem to get the same value.
So when you create the thread pass the value:
pthread_create(&thr, NULL, fonction_thread, (void *) (intptr_t) i)
And in the function do the opposite cast to get the value:
int n = (int) (intptr_t) arg;
Upvotes: 3