pthread_join会损坏堆栈中的pthread_create参数

pthread_join会损坏堆栈中的pthread_create参数,c,linux,multithreading,C,Linux,Multithreading,我从一本高级Linux编程书中获得了这段代码。当我尝试在Linux 64位环境下执行代码时,which\u prime变量的值在pthread\u join()函数调用后损坏(更改为0) 在本例中,为什么运行pthread\u join后,which\u prime的值会损坏 通常,即使调用其他函数,如pthread\u join(),我们也可以在main中安全地使用传递给pthread\u create函数的第4个参数吗 #包括 #包括 /*计算连续素数(效率很低)。归还 第N个素数,其中N是

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

在本例中,为什么运行pthread\u join后,
which\u prime
的值会损坏

通常,即使调用其他函数,如
pthread\u join()
,我们也可以在main中安全地使用传递给pthread\u create函数的第4个参数吗

#包括
#包括
/*计算连续素数(效率很低)。归还
第N个素数,其中N是*ARG指向的值*/
void*计算素数(void*arg)
{
int候选者=2;
int n=*((int*)arg);
而(1){
智力因素;
int是_素数=1;
/*通过连续除法测试素性*/
对于(系数=2;系数<候选;++系数)
如果(候选百分比因子==0){
是_素数=0;
打破
}
/*这就是我们要找的质数吗*/
if(is_素数){
如果(--n==0)
/*返回所需的素数作为线程返回值*/
返回(作废*)候选人;
}
++候选人;
}
返回NULL;
}
int main()
{
pthread\u t线程;
int,其中_素数=5000;
整数素数;
/*启动计算线程,直到第5000个素数*/
pthread_create(&thread,NULL,&compute_prime,&which_prime);
/*在这里做一些其他的工作*/
/*等待素数线程完成,然后获取结果*/
pthread_join(thread,(void*)和prime);
/*打印计算出的最大素数*/
printf(“第%d个素数是%d.\n”,它是素数,素数);
返回0;
}

我们已经到了一个时间点,在
int
指针之间转换不再安全。这是因为在64位系统中,指针是64位的,而
int
只有32位

假设32位
int
和64位指针,下面是代码中发生的情况。
pthread\u join
的第二个参数是指向指针的指针。换句话说,您应该传递指针的地址(64位值的地址)。而是传递
prime
(32位值的地址)的地址。当
pthread\u join
写入结果时,它会覆盖
which\u prime
,因为
which\u prime
紧跟在内存中的
prime
之后

要解决此问题,需要避免在
int
s和指针之间进行转换。一种方法是避免使用第二个参数
pthread\u 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;
}
#包括
#包括
#定义NUM_线程20
类型定义结构
{
成功;
int输入;
整数输出;
}stData;
void*doSomething(void*arg)
{
stData*dataptr=arg;
dataptr->success=1;
dataptr->output=dataptr->input*2;
返回NULL;
}
内部主(空)
{
int i;
pthread_t id[NUM_THREADS];
stData data[NUM_THREADS]={{0};
对于(i=0;i
或使用根据标准专门设计的足够大的整数类型来容纳数据指针:
intptr\u t
@WhozCraig通常,我认为最好尽量避免在指针和整数类型之间转换。这是可以避免强制转换的情况之一。如果有多个子线程,会发生什么情况?我们如何从每个线程捕获结果?我们可以使用互斥来保护相同的数据结构,并让每个线程更新数据结构的一部分,但是还有其他(更好的)方法吗?@m-adolf--我修改了示例代码以演示如何启动多个线程,每个线程都有自己的数据。我在
main
中声明了一个
数据
结构数组,然后向每个线程传递一个不同的
数据
结构--仔细查看第二个参数。
#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;
}