[英]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.