[英]Using a global struct with pthreads in C
我正在尝试模拟一段时间内进入银行并由出纳员服务的客户。 我正在使用一个线程来确定客户是否通过到达率进入银行,并正在使用多个线程来代表服务费率的柜员。 我正在使用一个结构来保存时间,到达率,服务率,出纳员人数和客户等待队列。 我试图在所有线程之间共享该结构,但出现“解引用指针”错误和“在某种非结构中请求成员x”错误。
//Used to store information input by user and the customer queue
struct shiftInfo {
int tellers;
int serviceTime;
int simTime;
int sampleInterval;
int threadID;
float arrivalRate;
int Q[]; //Customer Queue
};
信息通过命令行从命令行传递到结构中
struct shiftInfo *Q = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
struct shiftInfo info;
info.simTime = atoi(argv[1]);
info.arrivalRate = atof(argv[2]);
info.tellers = atoi(argv[3]);
info.serviceTime = atoi(argv[4]);
info.sampleInterval = atoi(argv[5]);
//Initiates Q to 0
for (int i = 0; i < maxCust; i++)
info.Q[i] = 0;
柜员,计时器和客户线程由主线程创建和终止
//Manager thread is main thread
pthread_t manager;
iret = pthread_create(&manager, NULL, mainThread, (void *)&info);
if (iret){
printf("ERROR: return code %d\n", iret);
exit(-1);
}
为了简短起见,我将只询问定时器线程,并希望将答案应用于其他线程。 计时器线程是通过以下方式在主线程中创建的:
int status;
struct shiftInfo *I = info;
pthread_t time;
status = pthread_create(&time, NULL, timer, (void *)info);
if (status){
printf("ERROR CODE: %d\n", status);
exit(-1);
}
计时器线程函数是:
void *timer(void *info){
int timeRemaining = info -> simTime;
while(timeRemaining){
sleep(1);
timeRemaining--;
}
}
对于“ int timeRemaining =信息-> simTime;” 我收到警告“取消引用空指针”,并且在不是结构或联合的情况下对成员âsimTime发出了错误请求。 任何建议,将不胜感激。
另外,我创建客户线程的方式与创建计时器线程的方式相同,但是会收到一条警告(警告:传递“ pthread_create”的参数3使指针从整数开始而没有强制转换[默认启用])在创建任何其他线程时不会收到线程,是什么原因造成的?
pthread_t customer;
status = pthread_create(&customer, NULL, customer, (void *)info);
if (status){
printf("ERROR CODE: %d\n", status);
exit(-1);
}
您犯了很多错误和错别字。 第一个错误是在这里:
struct shiftInfo *Q = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
struct shiftInfo info;
info.simTime = atoi(argv[1]);
info.arrivalRate = atof(argv[2]);
info.tellers = atoi(argv[3]);
info.serviceTime = atoi(argv[4]);
info.sampleInterval = atoi(argv[5]);
//Initiates Q to 0
for (int i = 0; i < maxCust; i++)
info.Q[i] = 0;
您在Q
分配了适当的空间量,但从未在任何地方使用过。 而是使用info
,它没有为info.Q
分配任何空间。 因此, info.Q[i] = 0
写入info
的边界。 建议的解决方法:
struct shiftInfo *info = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
info->simTime = atoi(argv[1]);
info->arrivalRate = atof(argv[2]);
info->tellers = atoi(argv[3]);
info->serviceTime = atoi(argv[4]);
info->sampleInterval = atoi(argv[5]);
//Initiates Q to 0
for (int i = 0; i < maxCust; i++)
info->Q[i] = 0;
下一个错误是:
status = pthread_create(&time, NULL, timer, (void *)info);
在您的代码中, info
是一个结构。 但是您正在尝试将其强制转换为指针。 如果您使用上面建议的修复程序,则info
将是一个指针,您可以将此代码保持不变。 您将需要确保对pthread_create
所有调用都传递(void *)info
而不是(void *)&info
。
最后一个错误是在这里:
void *timer(void *info){
int timeRemaining = info -> simTime;
尝试以下方法:
void *timer(void *arg){
struct shiftInfo *info = (struct shiftInfo *) arg;
int timeRemaining = info -> simTime;
这个片段是有问题的:
struct shiftInfo *Q = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
struct shiftInfo info;
info.simTime = atoi(argv[1]);
info.arrivalRate = atof(argv[2]);
info.tellers = atoi(argv[3]);
info.serviceTime = atoi(argv[4]);
info.sampleInterval = atoi(argv[5]);
//Initiates Q to 0
for (int i = 0; i < maxCust; i++)
info.Q[i] = 0;
内存分配很好,但是其他所有东西确实都是可疑的。 您的局部变量info
的Q
成员中有零个元素,因此您无法使用for
循环可靠地对其for
初始化。 还不清楚您打算如何处理info
; 您为什么不初始化Q
(指针,如果我可以这么说的话,是一个错误选择的名称)。 您应该使用:
struct shiftInfo *shift = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
shift->simTime = atoi(argv[1]);
shift->arrivalRate = atof(argv[2]);
shift->tellers = atoi(argv[3]);
shift->serviceTime = atoi(argv[4]);
shift->sampleInterval = atoi(argv[5]);
for (int i = 0; i < maxCust; i++)
shift->Q[i] = 0;
现在,您可以使用shift
(或任何您选择的调用方式)来设置全局指针。 请注意,您不能有效地将具有灵活数组成员的结构用作全局变量(指向它们的全局指针-是;全局变量-否),也不能将它们作为自动变量。 问题是您不能像这样为弹性数组成员分配任何空间。
您将需要考虑如何使用多个线程来控制对全局结构的访问,以及对全局结构的序列化访问是否将成为严重的瓶颈。 您可能需要互斥体,并且可能需要某些条件。
关于您的timer
代码:您需要将传递给struct ShiftInfo *
的void *
转换为struct ShiftInfo *
。
void *timer(void *vp)
{
struct ShiftInfo *info = vp;
int timeRemaining = info->simTime;
while(timeRemaining){
sleep(1);
timeRemaining--;
}
return 0;
}
请注意,您确实需要从函数中返回一个值。 另外,您需要考虑这是否会做您想要的事情。 它具有一个已更改的局部变量。 您可能希望将info
的值设置为剩余时间。 这就需要在每个操作中进行互斥访问。 我将假设您添加并初始化一个额外的成员:
pthread_t mutex;
到您的struct shifInfo
。
void *timer(void *vp)
{
struct shiftInfo *info = vp;
if (pthread_mutex_lock(&info->mutex) != 0)
return 0; // Report error before returning?
int *timeRemaining = &info->simTime;
while (*timeRemaining > 0)
{
if (pthread_mutex_unlock(&info->mutex) != 0)
return 0; // Report error before returning?
sleep(1);
if (pthread_mutex_lock(&info->mutex) != 0)
return 0; // Report error before returning?
(*timeRemaining)--;
}
if (pthread_mutex_unlock(&info->mutex) != 0)
return 0; // Report error before returning?
return 0;
}
在timer()函数中,您必须将info参数从(void *)强制转换为(struct shiftInfo *)
int timeRemaining = ((struct shiftInfo *)info) -> simTime;
另外,在创建客户时,应该像这样
status = pthread_create(&customer, NULL, customer, (void *)&info);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.