c - 将指向 void 的指针作为 pthread_join 的第二个参数传递
问题描述
下面是“高级 Linux 编程”的“线程”部分的示例程序,稍作修改以接收来自命令行参数的输入。
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* The calculation implemented below is not efficient
* Consult numerical algorithm for better solutions
*/
void *
compute_prime(void *arg)
{
int candidate = 2;
int n = *((int *) arg);
while (1)
{
int factor;
int is_prime = 1;
for (factor = 2; factor < candidate; ++factor)
if (candidate % factor == 0)
{
is_prime = 0;
break;
}
if (is_prime)
if (--n == 0)
return (void *)candidate;
++candidate;
}
return NULL;
}
int
main(int argc, char **argv)
{
pthread_t thread;
int which_prime = atoi(argv[1]);
int prime;
pthread_create(&thread, NULL, &compute_prime, &which_prime);
pthread_join(thread, (void *)&prime);
printf("The %dth prime number is %d.\n", which_prime, prime);
return 0;
}
让我困惑的是pthread_join
功能。它的原型是
pthread_join(pthread_t, void **)
所以第二个参数是 type void **
。同时,在程序void *
中传递了一个变量。我认为(void *)&prime
确实是一个void *
,对。但是如何将 avoid *
转换为void **
?我检查了源代码,第二个参数的赋值很简单*status = pthread->status
。
是void *
自动投射到void **
? 我认为这是不允许的,但这个程序使它似乎成为可能。像这样写是不正确的吗?
解决方案
to 的参数pthread_join
是一个指针,指向放置您要加入的线程的“退出值”的位置。该退出值(pthread_exit
传递给的线程函数的参数或返回的值pthread_create
)是 a void *
,所以参数pthread_join
是 a void **
。
现在令人困惑的是,在 C 中, avoid *
可以在没有强制转换的情况下隐式转换为任何指针类型。因此,将您传递给的值转换为(void *)
然后允许它被隐式转换void **
并传递。问题是,如果你传递的地址实际上不是 a void *
,你会得到未定义的行为。在此示例中,在 64 位机器上, avoid *
是 8 个字节,而 aint
可能只有 4 个字节,因此这可能会破坏紧接在 . 之后的堆栈帧中的任何内容prime
。那可能是which_prime
,所以这可能会打印出The 0th prime is
... 无论您最初传递的值是什么。0
或者它可能会在大端机器上打印素数。
推荐阅读
- r - 用 tmerge 或 SurvSplit 重塑纵向数据集?
- element-ui - 您如何使用 element-ui-el-table-draggable、Element UI 拖动列?
- python - Python中处理3D数组(矩阵)的最佳方法是什么
- python - 错误:AttributeError:模块“numpy”没有属性“sqrt”
- c# - SQLiteConnection 类中的“SetPassword”或“ChangePassword”在哪里?
- java - 不能将 ViewDataBinding 类用于通用 ViewHolder
- python - 如何使用嵌套列表创建 Spark 表
- macos - macOS虚拟机的CPU缓存性能比宿主机低50%左右
- wordpress - 如何修改 WooCommerce 预订中的“已付费”预订状态标签
- laravel - 在 app.js laravel 上创建全局方法 vue