pthread_create()函数被调用时传递多个参数?

131

我需要将多个参数传递给一个我想在单独线程上调用的函数。我已经阅读了典型的做法是定义一个结构体,将结构体的指针传递给函数,并对参数进行解引用。然而,我无法让这个方法起作用:

#include <stdio.h>
#include <pthread.h>

struct arg_struct {
    int arg1;
    int arg2;
};

void *print_the_arguments(void *arguments)
{
    struct arg_struct *args = (struct arg_struct *)args;
    printf("%d\n", args -> arg1);
    printf("%d\n", args -> arg2);
    pthread_exit(NULL);
    return NULL;
}

int main()
{
    pthread_t some_thread;
    struct arg_struct args;
    args.arg1 = 5;
    args.arg2 = 7;

    if (pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0) {
        printf("Uh-oh!\n");
        return -1;
    }

    return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}

这个的输出结果应该是:
5
7

但是当我运行它时,实际上得到的结果是:

141921115
-1947974263

有人知道我做错了什么吗?


4
尝试将它分配到堆上? - Carson Myers
1
@Carson 为什么那会有影响呢? - sigjuice
8
你的结构体应该至少和你的线程同生命周期。如果你创建一个线程并从调用pthread_create()函数的函数返回,那么在栈上分配的结构体可能会被其他数据覆盖,并可能在你的线程函数中引起问题。在这个例子中,这不是一个问题,因为创建线程会等待工作线程完成后再返回。 - Commodore Jaeger
1
@Commodore Jaeger 哦!谢谢,那就是我在处理另一个问题时遇到的问题。正如Carson所说,我通过使用malloc()在堆上分配它来解决了这个问题。现在这更有意义了。 - Michael
9个回答

97
由于您使用了以下代码行:

struct arg_struct *args = (struct arg_struct *)args;

而不是以下格式:

struct arg_struct *args = arguments;

因此,您需要进行更正。

9
@sigjuice,对我来说不起作用。我看到编译错误:从“void”到“arg_struct”的无效转换。 - Neshta
1
@Neshta: 这意味着你没有使用C编译器,但可能是在使用C++编译器。在这种情况下,你应该使用std::thread代替。 - Chris Dodd

27

使用

struct arg_struct *args = (struct arg_struct *)arguments;

替换为

struct arg_struct *args = (struct arg_struct *)args;

6

main()有它自己的线程和堆栈变量。要么在堆上分配'main()'中的'args'内存,要么将其作为全局变量。

struct arg_struct {
    int arg1;
    int arg2;
}args;

//declares args as global out of main()

然后当然需要将引用从args->arg1改为args.arg1等等。


3

使用:

struct arg_struct *args = malloc(sizeof(struct arg_struct));

然后像这样传递这些参数:

pthread_create(&tr, NULL, print_the_arguments, (void *)args);

不要忘记免费的参数!;)

3

我和原帖作者Michael有同样的问题。

尝试应用之前提交的答案,但没有成功。

经过一些尝试和错误,这是我修改后能够工作的代码版本(至少对我而言是有效的!)。仔细观察,你会发现它与之前发布的解决方案有所不同。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

struct arg_struct
{
   int arg1;
   int arg2;
} *args;

void *print_the_arguments(void *arguments)
{
   struct arg_struct *args = arguments;
   printf("Thread\n");
   printf("%d\n", args->arg1);
   printf("%d\n", args->arg2);
   pthread_exit(NULL);
   return NULL;
}

int main()
{
   pthread_t some_thread;
   args = malloc(sizeof(struct arg_struct) * 1);

   args->arg1 = 5;
   args->arg2 = 7;

   printf("Before\n");
   printf("%d\n", args->arg1);
   printf("%d\n", args->arg2);
   printf("\n");


   if (pthread_create(&some_thread, NULL, &print_the_arguments, args) != 0)
   {
      printf("Uh-oh!\n");
      return -1;
   }

   return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}

2
在这段代码的线程创建中,传递了一个函数指针的地址。 原始代码如下: pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args != 0) 应该修改为: pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args) 一个好的记忆方法是,这个函数的所有参数都应该是地址。 some_thread 是静态声明的,所以使用 & 可以正确地发送地址。
我会创建一个 pthread_attr_t 变量,然后对其使用 pthread_attr_init() 并传递该变量的地址。但是,传递一个 NULL 指针也是有效的。
在函数标签前面加上 & 是导致问题的原因。已经使用的标签是一个指向函数的 void*,所以只需要标签本身即可。
在最后一个参数中加上 != 0 似乎会导致不确定的行为。添加这个意味着传递的是一个布尔值而不是一个引用。
Akash Agrawal的答案也是解决这段代码问题的一部分。

1
print_the_arguments函数的参数是arguments,所以你应该使用:
struct arg_struct *args = (struct arg_struct *)arguments. 

1
struct arg_struct *args = (struct arg_struct *)args;

--> 这个任务是错误的,我的意思是在这种情况下应该使用可变参数。 干杯!!!


0

由于询问相同问题但针对C ++被视为重复,我可以提供C ++代码作为答案。

//  hello-2args.cpp
// https://dev59.com/_XM_5IYBdhLWcg3wgjS2
#include <iostream>
#include <omp.h>
#include <pthread.h>
using namespace std;

typedef struct thread_arguments {
  int thrnr;
  char *msg;
} thargs_t;

void *print_hello(void *thrgs) {
  cout << ((thargs_t*)thrgs)->msg << ((thargs_t*)thrgs)->thrnr << "\n";
  pthread_exit(NULL);
}

int main(int argc, char *argv[]) {
  cout << " Hello C++!\n";
  const int NR_THRDS = omp_get_max_threads();
  pthread_t threads[NR_THRDS];
  thargs_t thrgs[NR_THRDS];
  for(int t=0;t<NR_THRDS;t++) {
    thrgs[t].thrnr = t;
    thrgs[t].msg = (char*)"Hello World. - It's me! ... thread #";
    cout << "In main: creating thread " << t << "\n";
    pthread_create(&threads[t], NULL, print_hello, &thrgs[t]);
  }
  for(int t=0;t<NR_THRDS;t++) {
    pthread_join(threads[t], NULL);
  }
  cout << "After join: I am always last. Byebye!\n";
  return EXIT_SUCCESS;
}

使用以下其中一种方法进行编译和运行:

g++ -fopenmp -pthread hello-2args.cpp && ./a.out # Linux
g++ -fopenmp -pthread hello-2args.cpp && ./a.exe # MSYS2, Windows

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接