windyear
windyear

Reputation: 15

What happen if passing the address of the stack variable to the pthread function?

I write a program to let the threads executes orderly.But when I pass a stack variable's address to the thread function and the program just wait always.Here is the program:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t order_cond = PTHREAD_COND_INITIALIZER;
int count = 0;

void* thread_print(void* num){
    sleep(10);
    int number = *(int*)num;
    //printf("%d", number);
    for(int i = 0; i < 10; i++){
        pthread_mutex_lock(&mutex);
        while((count%3)!=number){
            pthread_cond_wait(&order_cond, &mutex);
        }
        switch(number){
            case 0:{
                printf("A");
                break;
            }
            case 1:{
                printf("B");
                break;
            }
            case 2:{
                printf("C");
                break;
            }
        }
        count++;
        pthread_mutex_unlock(&mutex);
        pthread_cond_broadcast(&order_cond);
    }
    return (void*)0;
}

int main(){
    pthread_t p_id[3];
    printf("fail\n");
    void* tret;
    for(int i = 0; i<3;i++){
        int success = pthread_create(&p_id[i], NULL, thread_print, (void*)&i);
        if(success != 0){
            printf("fail\n");
        }
    }
    for(int i = 0; i < 3; i++){
        pthread_join(p_id[i], &tret);
    }
    //sleep(10);
    pthread_mutex_lock(&mutex);
    while(count < 30){
        pthread_cond_wait(&order_cond, &mutex);
    }
    pthread_mutex_unlock(&mutex);
    return 0;
}

I make some effort.When I pass the i to the thread function and use int number = (int)num, it can works very well. So what happen when I just pass the address of i to the thread function?

Upvotes: 0

Views: 617

Answers (1)

John Bollinger
John Bollinger

Reputation: 181932

But when I pass a stack variable's address to the thread function and the program just wait always.

There is no inherent problem with passing an automatic variable's address to a thread function. In fact, it's fairly common to do so. There is a problem, however, with the thread function dereferencing the pointer after the lifetime of the pointed-to variable ends, and there may be a different kind of problem if the value of the pointed-to variable is changed by another thread, such as the parent thread.

Your program exhibits both kinds of problems: it passes the address of local variable i and then changes the value of that variable, and then that variable's lifetime ends when the loop terminates, which can easily happen before the threads try to use the pointer.

You could solve both problems with appropriate synchronization to ensure that the thread function reads the variable before the loop moves to the next iteration. That would be a correct solution for every conforming implementation.

It might be easier, however, to convert i to a pointer, pass the result, and have the thread function convert it back. Both conversions exhibit implementation-defined behavior, but in practice, this works fine on most systems. Your implementation's documentation should provide sufficient detail to determine whether it supports that approach, if you want to be certain.

For example:

    // Note that 'i' itself is converted to void *
    int success = pthread_create(&p_id[i], NULL, thread_print, (void *) i);
    // ...

void *thread_print(void *num) {
    // Note that 'num' is converted directly (back) to an int, not dereferenced
    int number = (int) num;
    // ...

Note, too, that sleep() does not solve synchronization problems. It best, it hides them, but in your particular case it accentuates them.

Upvotes: 1

Related Questions