pthread_join 破坏了堆栈中的 pthread_create 参数

m-a*_*olf 5 c linux multithreading

我从一本高级 Linux 编程书中得到了这段代码。当我尝试在 Linux 64 位环境下执行代码时which_primepthread_join()函数调用后变量的值会损坏(更改为 0)。

在此示例中,为什么which_prime在运行 pthread_join 后会损坏的值?

一般来说,即使我们调用其他函数,我们是否可以在 main 中安全地使用传递给 pthread_create 函数的第 4 个参数pthread_join()

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

/* Compute successive prime numbers (very inefficiently). Return the
Nth prime number, where N is the value pointed to by *ARG. */
void* compute_prime (void* arg)
{
    int candidate = 2;

    int n = *((int*) arg);
    while (1) {
        int factor;
        int is_prime = 1;
        /* Test primality by successive division. */
        for (factor = 2; factor < candidate; ++factor)
            if (candidate % factor == 0) {
                is_prime = 0;
                break;
            }
        /* Is this the prime number we’re looking for? */
        if (is_prime) {
            if (--n == 0)
                /* Return the desired prime number as the thread return value. */
                return (void*) candidate;
        }
        ++candidate;
    }
    return NULL;
}

int main ()
{
    pthread_t thread;
    int which_prime = 5000;
    int prime;
    /* Start the computing thread, up to the 5,000th prime number. */
    pthread_create (&thread, NULL, &compute_prime, &which_prime);
    /* Do some other work here... */
    /* Wait for the prime number thread to complete, and get the result. */
    pthread_join (thread, (void*) &prime);
    /* Print the largest prime it computed. */
    printf(“The %dth prime number is %d.\n”, which_prime, prime);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

use*_*109 4

int我们已经到了在 an和 a之间进行转换不再安全的时间点pointer。这是因为在 64 位系统中,指针是 64 位,但 anint只是 32 位。

因此,假设使用 32 位int和 64 位指针,代码中将发生以下情况。第二个参数pthread_join是指向指针的指针。换句话说,您应该传递指针的地址(64 位值的地址)。prime相反,您传递的是(32 位值的地址)的地址。当pthread_join写入结果时,它会覆盖which_prime,因为which_primefollowprime在内存中。

要解决此问题,您需要避免在ints 和指针之间进行转换。一种方法是避免使用 的第二个参数pthread_join,如以下代码所示。

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

#define NUM_THREADS 20

typedef struct
{
    int success;
    int input;
    int output;
} stData;

void *doSomething( void *arg )
{
    stData *dataptr = arg;

    dataptr->success = 1;
    dataptr->output  = dataptr->input * 2;
    return NULL;
}

int main( void )
{
    int i;
    pthread_t id[NUM_THREADS];
    stData data[NUM_THREADS] = {{0}};

    for ( i = 0; i < NUM_THREADS; i++ )
    {
        data[i].input = i + 1;
        pthread_create( &id[i], NULL, doSomething, &data[i] );
    }

    for ( i = 0; i < NUM_THREADS; i++ )
    {
        pthread_join( id[i], NULL );

        if ( data[i].success )
            printf( "thread %2d: input=%2d output=%2d\n", i+1, data[i].input, data[i].output );
        else
            printf( "thread %2d: failed\n", i+1 );
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)