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)