2016-10-12 50 views
2

中編譯的以下c代碼中的分段錯誤我們模擬了一個有一位廚師的唐杜裏雞肉午餐自助餐廳和 多個客人,這與單個生產者/多個消費者問題類似。我們 實現一個程序與多個線程,其中每個線程持有一個廚師或客人。 我們還應用了一個同步工具 - 信號量,它可以解決將公共資源與多個線程同步的問題。通過這個項目,我們將學習如何創建多線程進程以及如何使用信號量來同步線程。我們在linux

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

struct threadInfo 
{ 
int id; 
}; 

/* input variables */ 
int nofCustomers=4,item,nofChicken=3; 
pthread_attr_t attr; /*Set of thread attributes*/ 
pthread_t chef_t,customer_t[100]; 
/* the semaphores */ 
sem_t full, empty; 
void *chef(void *param); /* the producer thread */ 
void *customer(void *param); /* the consumer thread */ 

void initializeData() 
{ 

/* Create the full semaphore and initialize to 0 */ 
sem_init(&full, 0, 0); 

/* Create the empty semaphore and initialize to BUFFER_SIZE */ 
sem_init(&empty, 0, nofChicken); 

/* Get the default attributes */ 
pthread_attr_init(&attr); 

} 

生產者

/* Producer Thread */ 
void *chef(void *param) 
{ 
printf("Chef Starts Cooking\n"); 
while(1) 
{ 
    /* acquire the empty lock */ 
    sem_wait(&empty); 

    if(insert_item()) 
    { 
    fprintf(stderr, " Producer report error condition\n"); 
    } 
    /* signal full */ 
    sem_post(&full); 
    sleep(1); 
} 
} 

消費者

/* Consumer Thread */ 
void *customer(void *param) 
{ 
    int toeat=1+rand()%4,ate=0,t=nofCustomers; 
    int *id=(int*)param; 
    printf("Guest %d arrives and wants to eat %d food\n", id, toeat); 
    while(1) 
    { 
    /* aquire the full lock */ 
    sem_wait(&full); 

    if(remove_item()) 
    { 
     fprintf(stderr, "Consumer report error condition\n"); 
    } 
    else 
    { 
    ate++; 
     printf("Guest %d eats a tandoori chicken[%d/%d]\n", id,ate,toeat); 
     } 
    if(ate==toeat) 
    { 
     nofCustomers--; 
    printf("Guest %d finishes and exits\n",id); 
    } 
    if(nofCustomers==0) 
    { 
    printf("All guests finish eating and exit\n"); 
    break ; 
    } 
    /* signal empty */ 
    sem_post(&empty); 
    sleep(toeat); 
    } 
} 

INC臨界區

/* Cook food */ 
int insert_item() 
{ 
    /* When the item is not full,cook food 
    increment the item*/ 
    if(item <= nofChicken) 
    { 
    item++; 
    printf("Chef cooks one tandoori chicken.[%d/%d]\n",item,nofChicken); 
    return 0; 
    } 
    else 
    { /* Error the items are full */ 
     return -1; 
    } 
} 

DEC臨界區

/* Eat food */ 
int remove_item() { 
/* When the items is/are cooked, eat the item 
    i.e.., decrement the item */ 
    if(item > 0) 
    { 
    item--; 
    return 0; 
    } 
    else { /* Error no items */ 
    return -1; 
    } 
} 

主要功能在BOVE CODE

+3

你可以嘗試運行GDB中的代碼來準確找到段錯誤發生的位置嗎? – Matt

+3

按照建議使用gdb查找精確的seg斷層線。但對於初學者:'info-> id = i;'會導致seg故障,因爲info是一個未初始化的指針。其他錯誤包括將相同的'info'指針傳遞給所有線程,這意味着每個線程都會看到一個隨機值'info-> id',並且'main'在退出之前不會等待線程完成('pthread_join')。 – kaylum

+0

歡迎來到Stack Overflow!爲了幫助人們回答您的問題,您需要更加具體地瞭解錯誤。請[編輯]您的帖子以合併您運行[mcve]時獲得的確切堆棧跟蹤(最好使用複製+粘貼以避免轉錄錯誤)。 –

回答

1

首先,解決這些編譯錯誤:

g++ -std=c++17 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -O2 -Weffc++  39988874.cpp -o 39988874 
39988874.cpp: In function ‘void* chef(void*)’: 
39988874.cpp:43:25: error: ‘insert_item’ was not declared in this scope 
     if (insert_item()) { 
         ^
39988874.cpp:48:16: error: ‘sleep’ was not declared in this scope 
     sleep(1); 
       ^
39988874.cpp:36:18: warning: unused parameter ‘param’ [-Wunused-parameter] 
void *chef(void *param) 
        ^~~~~ 
39988874.cpp: In function ‘void* customer(void*)’: 
39988874.cpp:58:68: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int*’ [-Wformat=] 
    printf("Guest %d arrives and wants to eat %d food\n", id, toeat); 
                    ^
39988874.cpp:63:25: error: ‘remove_item’ was not declared in this scope 
     if (remove_item()) { 
         ^
39988874.cpp:67:77: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int*’ [-Wformat=] 
      printf("Guest %d eats a tandoori chicken[%d/%d]\n", id,ate,toeat); 
                      ^
39988874.cpp:71:54: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int*’ [-Wformat=] 
      printf("Guest %d finishes and exits\n",id); 
                ^
39988874.cpp:79:20: error: ‘sleep’ was not declared in this scope 
     sleep(toeat); 
        ^
39988874.cpp:56:32: warning: unused variable ‘t’ [-Wunused-variable] 
    int toeat=1+rand()%4,ate=0,t=nofCustomers; 
           ^
39988874.cpp:81:1: warning: no return statement in function returning non-void [-Wreturn-type] 
} 
^ 
<builtin>: recipe for target '39988874' failed 
make: *** [39988874] Error 1 

(提示:你需要爲#include <unistd.h>sleep();還有,你要int id = ((threadInfo*)param)->id

有固定的,你會離開與

39988874.cpp: In function ‘int main()’: 
39988874.cpp:133:17: warning: ‘info’ may be used uninitialized in this function [-Wmaybe-uninitialized] 
     info->id=i; 
     ~~~~~~~~^~ 

這是相當明顯受到

引起
struct threadInfo *info; 
/* ... */ 
for (i = 1; i <= nofCustomers; i++) { 
    info->id=i; 
} 

這是你的問題。您需要將info指向一些有效的存儲。

-1

編譯代碼時使用-Wall和消除(或者至少仔細觀看)

int main() 
{ 
    /* Loop counter */ 
    int i; 
    struct threadInfo *info; 

    //input (Havent written code for input includes nofChicken andnofCustomers 

    /* Initialize the app */ 
    initializeData(); 

    /* Create the producer thread */ 
    pthread_create(&chef_t,&attr,chef,NULL); 


    /* Create the consumer threads */ 
    for(i = 1; i <= nofCustomers; i++) 
{ 
    info->id=i; 
    pthread_create(&customer_t[i],&attr,customer,(void *)info); 
} 

return 0; 
} 

分割故障所有的警告。

+2

這不是一個答案。 – unwind

+0

如果你想一點點,你會明白,更好地教人使用 - 用他/她的每個分段錯誤來喚醒和消除所有的警告(見上面的確切警告)或垃圾郵件,因爲髒碼警告被禁用。 – Rus

+0

謝謝,我會考慮這一點。儘管如此,這不是問題的答案,而更多的是評論。 – unwind

相關問題