我编写了这个小程序来理解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 :(得分:5)
这是因为pthread_join
拥有原型void **
。它期望指针到类型为void *
的对象;它修改了这个void *
对象。现在碰巧你正在64位拱门上运行,其中data
和value
都是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);