Kar*_*ick 1 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;
}
Run Code Online (Sandbox Code Playgroud)
输出是
Argument passed is 5000
The number is 0 and return value is 5000.
Run Code Online (Sandbox Code Playgroud)
这是因为pthread_join有原型void **.它期望指向类型对象的指针void * ; 它修改了这个void *对象.现在碰巧你正在运行64位拱,其中data和value都是32位,并按顺序布局在内存中.修改void *从的地址开始了在内存布局对象int物体value则会覆盖的int对象data太多,因为这些都是32位-所以你会看到,data已被覆盖.但是,这是未定义的行为,因此任何事情都可能发生.
不要使用演员,因为他们只会隐藏问题.转换为a 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);
Run Code Online (Sandbox Code Playgroud)
如果编译时启用了警告.
但是,如果你真的想这样做,你必须这样做:
void *value;
pthread_join(thread, &value);
intptr_t value_as_int = (intptr_t)value;
Run Code Online (Sandbox Code Playgroud)
虽然它也不是真正可移植的,因为转换是实现定义的.
返回整数的最便携方式是返回指向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);
Run Code Online (Sandbox Code Playgroud)