使用pthread_create()传递结构体作为参数

17

我尝试在使用pthread_create()时将结构体作为第四个参数传递,代码如下:

pthread_create(&tid1, NULL, calca, &t); //t is the struct

现在每当我尝试访问结构体中的变量 - t.a,t.b或t.c时,都会出现错误 - 请求在非结构体或联合体中的成员。我应该使用什么替代方法来将结构体传递到线程中?
8个回答

24
你可能是在与pthread_create相同的作用域内创建结构体。一旦该作用域被退出,该结构体将不再有效。
尝试在堆上创建一个指向该结构体的指针,并将该结构体指针传递给线程。不要忘记在某个地方删除该内存(如果您将永远不再使用它,则在线程中 - 或者在您不再需要时)。
另外,像cyberconte提到的那样,如果您将从不同的线程访问该数据,您将需要使用互斥锁或关键段锁定对其进行访问。
编辑于2009年5月14日下午12:19:如其他人所提到的,您必须将参数强制转换为正确的类型。
如果您正在传递全局结构变量(似乎您坚持这样做),则您的线程函数将必须将其转换为该类型:
void my_thread_func(void* arg){
    my_struct foo = *((my_struct*)(arg)); /* Cast the void* to our struct type */
    /* Access foo.a, foo.b, foo.c, etc. here */
}

或者,如果你正在传递指向你的结构体的指针:

void my_thread_func(void* arg){
    my_struct* foo = (my_struct*)arg; /* Cast the void* to our struct type */
    /* Access foo->a, foo->b, foo->c, etc. here */
}

实际上,我在主函数中创建了线程,并在包含头文件后立即创建了结构。因此它应该可以被所有函数访问(如有错误请指正)。 - skinderneath
你最近的编辑是迄今为止这里最有用的帖子。谢谢。 - skinderneath
培根值得保存。 - Lyndsey Ferguson

2

如果你在线程函数中,传递的参数是 void* 类型。在使用之前,需要将其转换为 struct。

void my_thread_func(void* arg){
    my_struct foo = (my_struct)(*arg); /* Cast the void* to our struct type */
    /* Access foo.a, foo.b, foo.c, etc. here */
}

我已经这样做了,但现在我收到一个“dereferencing 'void *' pointer”错误。 - skinderneath
Harper 的意思是写成:my_struct foo = *(my_struct *)arg; 或者 my_struct *foo = (my_struct *)arg; - Jonathan Leffler
使用了这个想法和Lyndsey Ferguson在2009年5月14日下午12:19发布的编辑。 - skinderneath
是的,C风格的转换不是我的强项,而且我已经好几年没有使用pthread_create了。我更喜欢C++和一个好的线程库。 - Harper Shelby

1
  1. 创建一个信号量

  2. 创建另一个结构体,其中包括指向您的结构体和信号量句柄的指针

  3. 将指向此新结构体的指针传递给pthread_create

  4. 在父线程中,即调用pthread_create的线程中,等待信号量

  5. 在子线程中,将结构体成员复制到本地变量或其他位置保存

  6. 在子线程中,发出信号量

  7. 在父线程中,关闭信号量


0
这是一个例子: 这个函数将创建线程并传递结构参数。
pthread_create (& threads[i], NULL , PrintMessage ,(void *) &tab[i]);

这是线程函数:

 void *PrintMessage(void * arg)
{
struct param *mes_param ; mes_param = (struct param*) arg;
printf (" message from thread %d: %s\n", mes_param -> num_message ,
mes_param -> message );
pthread_exit(NULL);
}

结构体:

struct param {
int num_message ;
char* message ; };
struct param tab[MAX_THREADS];

0

我以前经常犯其他答案中列出的相同错误,但现在我采取了稍微不同的方法,将潜在的错误从线程函数移动到pthread_create调用。

我以“正常”的方式声明和定义线程函数:

void *ThreadFunction(sPARAMETERS *Params) {

  // do my threading stuff...

}

当我调用pthread_create时,我需要使用一个强制转换:

pthread_create(&ThreadId,0,(void*(*)(void*)) &ThreadFunction,&Params);

我几乎从不忘记在参数上使用 &,编译器会处理我在另一端犯的任何错误。对于回调也非常有效。


从技术上讲,这是未定义的行为 - 尽管在大多数编译器上,它对于普通结构指针可以工作。不要尝试使用C++成员函数指针... - bdonlan
我不明白这如何解决我的问题。你使用的那些转换方式太过神秘了。 - skinderneath

0

my_struct foo = (my_struct)(*arg); 是不正确的 尝试使用 my_struct *foo = (my_struct *)(arg);
并且,在调用线程的函数中, 确保它是静态的(这样指向的内存不会在迷雾中丢失)


0

如果没有其他东西需要该参数,您可以使用共享内存或全局变量。或者,如果这些是依赖数据的线程,则可以使用链表。

只需记住锁定正在进行线程共享的变量即可。

但是,如果没有实际的有问题代码,我就无法告诉您当前实现中出了什么问题。


0

这个错误信息意味着您没有对指针进行解引用。

您应该使用"t->a"而不是"t.a"

[me@myhost ~]$ cat testitx.c
struct x {
        int a, b;
};
int main(int argc, char *argv[]) { struct x y, *z;
z = &y z->a = 10; } [me@myhost ~]$ cc -c testitx.c testitx.c: In function `main': testitx.c:10: error: request for member `a' in something not a structure or union [me@myhost ~]$

没有帮助。我使用了Harper Shelby的解决方案,但是出现了“dereferencing 'void *' pointer”错误。 - skinderneath

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