简体   繁体   中英

Only first value returned from thread is wrong (C)

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

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM