我正在编写一个非常简单的代码,我需要使用一些线程。 当我创建第一种类型的线程时,我使用pthread_create传递参数:
fman thread_arg;
thread_arg.sd=sda;
char* split = strtok(buffer, "|");
thread_arg.wcount=atoi(split);
split = strtok(NULL,"");
strcpy(thread_arg.id, split);
pthread_create(&thread_temp, NULL, registerF, &thread_arg);
一切正常,但在函数registerF中我需要做这样的事情:
wman thread_arg;
thread_arg.sd=foremans_fd[ix];
thread_arg.fmanix=ix;
strcpy(thread_arg.id,tmpr);
pthread_create(&thread_temp, NULL, registerW, &thread_arg);
这些论点是我定义的结构:
typedef struct fman
{
int sd;
char id[100];
int wcount;
} fman;
typedef struct wman
{
int sd;
int fmanix;
char id[100];
} wman;
当我通过printf("%x,args)检查它时,我得到相同的地址,但内部的值不同。我的错误在哪里?
答案 0 :(得分:3)
这里可能存在一个问题:
fman thread_arg;
[...]
pthread_create(&thread_temp, NULL, registerF, &thread_arg);
请注意,thread_arg对象位于堆栈上,因此当声明它的函数返回时,它将被销毁(并可能被其他堆栈变量覆盖)。
另一方面, pthread_create()启动一个与该函数异步运行的线程,这意味着线程可以(并且经常会)在您摘录的函数返回后运行,这意味着当线程解除引用&thread_arg
时,thread_arg
可能已经被销毁,并且该指针现在指向稍后写入同一堆栈位置的其他一些数据。
除非你正在做一些特别的工作以确保struct的生命周期足够长以包含所有生成的线程对结构的访问,然后这个代码工作的事实是纯粹的运气(即调度程序刚好碰巧安排在销毁/覆盖结构之前运行并执行对结构的所有访问的线程。你绝对不能依赖它。
为了解决这个问题,你需要在堆上分配struct(这样当函数返回时它不会被销毁 - 生成的线程可以在使用它时释放struct) ,或者使用某种同步机制(例如条件变量)使主线程在函数内部阻塞,直到生成的线程表明它已经完成访问结构。
答案 1 :(得分:1)
正在运行的线程中的线程结构被视为一块内存并使用偏移量进行访问。由于你的fman和wman结构有不同的顺序(4 + 100 + 4)vs(4 + 4 + 100),所以你可能会得到正确的结构但是从不同的内存位置读取,因为通过了此线程的结构是fman,它被作为wman访问。
尝试将它们更改为相同的签名,如in,int,int,char *,它应该可以工作。