作为引用传递的变量的值在线程中更改

时间:2017-07-13 15:40:10

标签: c pthreads pthread-join

我编写了这个小程序来理解pthread_create和pthread_join但是我不明白为什么变量data的值在thread_join之后被改变了。它在调用pthread函数后打印为0。

#include <pthread.h>
#include <stdio.h>
void* compute_prime (void* arg)
{
        int n = *((int*) arg);
        printf("Argument passed is %d\n",n);
        return (void *)n;
}
int main ()
{
        pthread_t thread;
        int data = 5000;
        int value=0;

        pthread_create (&thread, NULL, &compute_prime, &data);
        pthread_join (thread, (void*) &value);
        printf("The number is %d and return value is %d.\n", data, value);
        return 0;
}

输出

Argument passed is 5000
The number is 0 and return value is 5000.

1 个答案:

答案 0 :(得分:5)

这是因为pthread_join拥有原型void **。它期望指针到类型为void *的对象;它修改了这个void *对象。现在碰巧你正在64位拱门上运行,其中datavalue都是32位,并按顺序排列在内存中。修改从void *对象int的地址开始在内存中布局的value对象,同时隐藏int对象data,因为这两者都是32位 - 因此您将看到data被覆盖。但是,这是未定义的行为,因此可能发生任何事情。

不要使用演员表,因为它们只会隐藏问题。转换为void *特别危险,因为void *可以隐式转换为任何其他类型,甚至是void **,即使通常它也是不正确的。如果您删除演员表,您很可能会收到警告或错误,如

thrtest.c: In function ‘main’:
thrtest.c:16:31: error: passing argument 2 of ‘pthread_join’ from 
                incompatible pointer type [-Werror=incompatible-pointer-types]
         pthread_join (thread, &value);

如果在启用警告的情况下进行编译。

如果你真的想这样做,你必须这样做:

void *value;
pthread_join(thread, &value);
intptr_t value_as_int = (intptr_t)value;

虽然它也不是真正可移植的,因为转换是实现定义的。

返回整数的最便携方式是返回指向malloc对象的指针:

int *return_value = malloc(sizeof (int));
*return_value = 42;
return return_value;

...

void *value;
pthread_join(thread, &value);
int actual = *(int *)value;
free(value);