类比较无效指针&背部

时间:2010-09-28 09:02:02

标签: c multithreading casting

我有一个功能:

void *findPos(void *param)
{
   int origPos=(int)param;
   ...
}

我称之为线程转换器:

pthread_create( &threadIdArray[i], NULL, findPos, (void *)i );

现在,这样,我得到origPos的值作为类型化的void指针参数,即。一世。这感觉就像是一个肮脏的黑客,以解决被允许只传递无效指针到线程运行器功能的限制。

这可以用更干净的方式完成吗?

修改

请注意,我在pthread_create() for循环中运行i函数,因此传递指向i的指针可能不是一个安全的选择。

5 个答案:

答案 0 :(得分:3)

当然:只提供指向int的指针,这是API设计者的意图:

void *findPos(void *param)
{
   int origPos=*(int *)param;
   ...
}

pthread_create( &threadIdArray[i], NULL, findPos, &i );

intvoid *之间的转换是不安全的,因为转换不一定是可逆的。

当线程开始执行时,您还必须确保i仍然有效(如果i具有自动存储持续时间,例如,如果调用函数也调用pthread_join(),则会出现这种情况。 )。

在你的情况下(i是一个循环变量),你应该在一个安全的位置复制变量的值,例如在堆上通过malloc()或者在具有适当的liefetime的堆栈上推送它:

static int args[THREAD_COUNT];

for(int i = 0; i < THREAD_COUNT; ++i)
{
    args[i] = i;
    pthread_create(&threadIdArray[i], NULL, findPos, args + i);
}

答案 1 :(得分:2)

好吧,你可以传递一个指向值的指针,或者将值包装在一个struct中并传递指针。后者本身并不是更清晰,但如果您需要在线程中使用多个int值的参数,则可扩展性更强。

<强>更新
我过去建议使用来自<stdint.h>的使用intptr_t来表示您打算将此整数转换为void *,或者更加仔细地阅读文档(谢谢,Christoph) :

  

以下类型指定一个带符号的整数类型,其属性是任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,结果将等于原始指针:intptr_t

这似乎表明,正如克里斯托夫所说,如果你走这条路,你就不安全了,所以不要

答案 2 :(得分:2)

您应该确保在您的系统上,参数的值在void-pointer内有足够的空间(请参阅数据类型intptr_t)。使用“直接”方法传递double值可能会出现问题。

我经常使用参数structur将值传递给线程(或其他)函数。

struct Param {
   double foo;
   int bar;
};  

Param param;
param.foo = 1.0;
param.bar = 1;

pthread_create( &threadIdArray[i], NULL, findPos, &param );

答案 3 :(得分:1)

如果你想拥有可移植的代码,这是一个你不应该做的黑客攻击。首先,从void*返回的转换未必如其他人所说的那样明确定义。

但不管怎样,这是一个肮脏的黑客攻击pthread_create API的所有可能的意图。只需使用以下内容:

size_t * threadId = calloc(n, sizeof(size_t));
for (size_t i = 0; i < n; ++i) {
   threadId[i] = i;
   ptread_create(...., &threadId[i]);
}

如果将相同的参数传递给所有线程,那么i上的拥塞就没有了。

答案 4 :(得分:0)

我真的不相信这是一个肮脏的黑客。维基百科在其pthreads example中也是如此。