2016-10-12 8 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); 
    } 
} 

ИНК в критической секции

/* 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; 
    } 
} 

В декабре критической секции

/* 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; 
    } 
} 

Основная функция

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; 
} 

вина Сегментация в Бове КОД

+3

Можете ли вы попробовать запустить код в GDB, чтобы найти, где именно происходит segfault? – Matt

+3

Используйте gdb как рекомендуется для поиска точной линии разлома seg. Но для начинающих: 'info-> id = i;' может вызвать ошибку seg, потому что 'info' является неинициализированным указателем. Другие ошибки включают передачу одного и того же указателя 'info' ко всем потокам, что означает, что каждый поток будет видеть случайное значение' info-> id', а также 'main' не дожидается завершения потоков (' pthread_join') перед выходом. – kaylum

+0

Добро пожаловать в переполнение стека! Чтобы помочь людям ответить на ваш вопрос, вам нужно быть более конкретным в отношении ошибки. Пожалуйста, отредактируйте свое сообщение, чтобы включить точную трассировку стека, которую вы получаете от запуска вашего [mcve] (желательно с помощью copy + paste, чтобы избежать ошибок транскрипции). –

ответ

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 при компиляции кода и устранить (или, по крайней мере, внимательно смотреть) все предупреждения.

+2

Это не ответ. – unwind

+0

Если вы подумаете немного, вы поймете, что лучше научить человека использовать -Все и устранить все предупреждения (см. Точное предупреждение выше) или спам SO со всеми его проблемами сегментации, которые будут определенно происходить из-за грязного кода с предупреждения отключены. – Rus

+0

Спасибо, я подумаю об этом. Тем не менее, это не ответ на вопрос, это скорее комментарий. – unwind