2016-10-12 11 views
2

1人のシェフと の複数のゲストを持つタンデオリチキンランチビュッフェレストランをシミュレートします。これは単一のプロデューサ/複数の消費者の問題に似ています。私たち は、それぞれがシェフまたはゲストのいずれかを保持する複数のスレッドを持つ1つのプログラムを実装します。 の共通リソースを複数のスレッドと同期させる問題を解決できる同期ツール - セマフォも1つ適用します。このプロジェクトでは、 マルチスレッドプロセスを作成する方法と、セマフォを使用してスレッドを同期させる方法を学びます。Linuxでコンパイルされた以下のCコードのセグメンテーションフォルト

#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

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

危険領域12月

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

セグメンテーションフォールトBOVEコード内の

+3

GDBでコードを実行して、segfaultの発生場所を正確に調べることはできますか? – Matt

+3

正確なsegフォールト・ラインを見つけるために、gdbをアドバイスとして使用してください。しかし、初心者のために 'info-> id = i;'は 'info'が初期化されていないポインタなので、segフォルトを引き起こす可能性があります。他のエラーには、すべてのスレッドに同じ 'info'ポインタを渡すことが含まれます。つまり、各スレッドは' info-> id'のランダムな値を参照し、 'main'はスレッドが終了するのを待たずに(' pthread_join')終了します。 – kaylum

+0

ようこそスタックオーバーフロー!人々があなたの質問に答えるのを助けるためには、エラーについてより具体的に説明する必要があります。あなたの[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 

(ヒント:あなたがsleep()ため#include <unistd.h>が必要になります。また、あなたは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

ちょっと考えてみると、壁を使用するように教えて、汚れたコードのために間違いなく起こるすべてのセグメンテーション違反ですべての警告(上記の正確な警告を参照)警告が無効になっています。 – Rus

+0

ありがとう、私はそれについて考えます。それでも、それは質問に対する答えではなく、それはもっとコメントです。 – unwind

関連する問題