3

New to C, I was reading here about how to properly pass an argument to a thread. What about if this argument needed to be passed to multiple threads? Where/how should I use free()? Say:

void *foo(void *i) {
    int a = *((int *) i);  
    while(1){
        printf("foo running \n");
        sleep(1);
    }
}

void *bar(void *i) {
    int a = *((int *) i);   
    while(1){
        printf("bar running \n");
        sleep(1);
    }
}

int main() {
    pthread_t threads[2];
    int i;
    for (i = 0; i < 2; i++ ) {
        int *arg = malloc(sizeof(*arg));
        if ( arg == NULL ) {
            fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
            exit(1);
        }
        *arg = i;
        pthread_create(&threads[0], NULL, foo, arg);
        pthread_create(&threads[1], NULL, bar, arg);
    }
    for (i = 0; i < 2; i++){
        pthread_join(threads[i],NULL);
    }
    return 0;
}

Is calling free(arg); in main after spawning the threads the same thing / safe?

Community
  • 1
  • 1
Stephan GM
  • 245
  • 3
  • 15

2 Answers2

2

You need to make sure both threads have finished before calling free(arg).

That means you can do it after you call pthread_join on both threads.

for (i = 0; i < 2; i++){
    pthread_join(threads[i],NULL);
}
free(args);
dbush
  • 205,898
  • 23
  • 218
  • 273
  • I am going to accept Jaochim's answer because it also points out that in this scenario, it isn't necessary to dynamically allocate it. But +1 cause this us super useful! Thanks – Stephan GM Aug 01 '16 at 17:53
2

If all threads needs the exact same argument, and they are not modifying the argument, there's no need to allocate it dynamically at all, instead just declare it as a variable at function scope in the main function. If there's no dynamic allocation, there's no need to free it.

On the other hand if you need separate arguments in a loop like you do, you need to keep track of all arguments, for example using an array:

// Rest of program...

#define NUMBER_OF_ITERATIONS 2

int main(void)
{
    int args[NUMBER_OF_ITERATIONS];
    pthread_t threads[NUMBER_OF_ITERATIONS][2];

    // Create threads
    for (unsigned i = 0; i < NUMBER_OF_ITERATIONS; ++i)
    {
        args[i] = i;
        pthread_create(&threads[i][0], NULL, foo, &args[i]);
        pthread_create(&threads[i][1], NULL, bar, &args[i]);
    }

    // Wait for threads to finish
    for (unsigned i = 0; i < NUMBER_OF_ITERATIONS; ++i)
    {
        pthread_join(threads[i][0]);
        pthread_join(threads[i][1]);
    }

    return 0;
}

The program above also solves another problem you have, when you create a total of four threads but only join two.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621