2017-07-13 43 views
1

我写了这个小程序来理解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. 
+0

''中pthread_join' value'被设置为线程的返回值。这里,这意味着线程函数返回的'n'的值为 –

+0

@CraigEstey问题是数据变化的原因。我没有看到这段代码改变它,即使在'return(void *)n;'中投了错。可能有代码缺失。 –

+0

'return(void *)n;'返回一个指向局部变量的指针,不是吗? –

回答

5

这是因为pthread_join有原型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 ated对象:

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

... 

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

正是我现在发现的;) –

+0

如果你只是想从一个线程函数返回一个数字,把它转换为'intptr_t',但是想到...... –

+0

是的,那么可以通过将数据定义为'unsigned long long int'来确认这一点? –

相关问题