C:如何安全正确地将多个参数传递给pthread?

时间:2014-06-06 20:37:21

标签: c multithreading pthreads

考虑这个简单的代码:

void* threadFunction(void* arg) {

    int argument=(int)arg;

    printf("%d recieved\n", argument);

    return NULL;
}


int main(int argv, char* argc[]) {

    int error;
    int i=0;
    pthread_t thread;

    int argument_to_thread=0;

    if ((error=pthread_create(&thread, NULL, threadFunction, (void*)argument_to_thread))!=0) {
        printf("Can't create thread: [%s]\n", strerror(error));
        return 1;
    }

    pthread_join(thread, NULL);


    return 0;
}

这很有效,但有两件事让我烦恼。
首先,我想向threadFunction()发送多个参数。
当然,我可以传递一个指向数组的指针,但是如果我想传递两个不同类型的参数呢? (比如intchar*)怎么办?

在这里困扰我的第二件事是我在编译上面时得到的警告......

test2.c: In function ‘threadFunction’:
test2.c:8:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  int argument=(int)arg;
               ^
test2.c: In function ‘main’:
test2.c:24:59: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
  if ((error=pthread_create(&thread, NULL, threadFunction, (void*)argument_to_thread))!=0) {
                                                           ^

现在,我可以通过这样做来消除这种情况:

if ((error=pthread_create(&thread, NULL, threadFunction, (void*)&argument_to_thread))!=0) {
    printf("Can't create thread: [%s]\n", strerror(error));
    return 1;
}

但是,让我们说我不想通过引用传递它...有没有办法传递,说...一个int,按值作为参数,而编译器没有警告我? / p>

3 个答案:

答案 0 :(得分:2)

有两种方法可以做到这一点:

  1. 使用malloc获取参数结构的存储空间,并让新线程负责在参数完成后调用free。 (注意:如果pthread_create失败,则需要在失败路径中free此存储。)

  2. 使用信号量(或其他同步,但信号量是目前最轻的)。

  3. 以下是后者的一个例子:

    struct args {
        int a;
        char *b;
        sem_t sem;
    };
    
    void *thread_func(void *p)
    {
        struct args *args = p;
        int a = args->a;
        char *b = args->b;
        sem_post(args->sem);
        ...
    }
    
        /* in caller */
        struct args args;
        args.a = ...;
        args.b = ...;
        sem_init(&args.sem, 0, 0);
        pthread_create(&tid, 0, thread_func, &args);
        sem_wait(&args.sem);
        ...
    

答案 1 :(得分:2)

如果你想通过值传递但警告消失,请使用此演员:

(void *)(uintptr_t)argument_to_thread

通过uintptr_t的中间演员避免了尺寸不匹配。同样,在回退时,请使用:

(int)(uintptr_t)voidptr_arg

如评论中所述,不一定建议使用上述方法,因为它依赖于实现定义的行为。假设您不需要全范围的int但只需要很小的范围,那么完全可移植的方法是:

static const char int_to_ptr_trick[MAXVAL];
void *ptr = int_to_ptr_trick + int_val;
int int_val = (char *)ptr - int_to_ptr_trick;

答案 2 :(得分:1)

传递整数的地址。

int argument = 123 ;
pthread_create(&thread, NULL, threadFunction, &argument)) ;

并在线程函数

 int argument= *(int*)arg ;

如果您希望传递多个参数,可以使用与上述示例相同的方法创建包含值的结构。

如果函数的参数为​​void *,则不能按值传递整数。您必须提供变量或结构的地址。