2017-08-10 6 views
0

私はCで読者とライターの問題のバリエーションを実装しようとしていますが、ライターはインクリメンタまたはデクリメンタのどちらでもかまいません。私が実装しようとしているコードは以下の通りです: "Segmentation Fault(core dumped)"というエラーが出ていますが、これをデバッグしようとしましたが、main()の#0 0x0000000000400d84からフィードバックを受け取りました。 誰かが私にこの障害を解決する方法のヒントを与える/私にこれを説明することができました おかげCセグメンテーションフォールト - 読者とライター

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

#define WAIT 20 
#define NEW 0 

#define DECREMENT 0 
#define INCREMENT 1 

#define TIME 5 
#define VALUE 1 
#define COMMON 0 


int readerCount = NEW; 
int total = 0; 
int v; 
sem_t mutex; 
sem_t access_data; 



int increment_or_decrement() { 
    int d; 
    return d = rand() % 2; 
} 

void *writer(void *arg) { 
    int version = increment_or_decrement(); 

    int *iID = (int *) arg; 
    int *dID = (int *) arg; 

    sleep(rand() % WAIT); 

    sem_wait(&access_data); 

    if (version == INCREMENT) { 
     fprintf(stderr, "Incrementer %d accessed the data\n", *iID); 
     total++; 
     fprintf(stderr, "Total: %d\n", total); 
    } 
    else { 
     fprintf(stderr, "Decrementer %d accessed the data\n", *dID); 
     total--; 
     fprintf(stderr, "Total: %d\n", total); 
    } 

    sleep(TIME); 

    sem_post(&access_data); 

    pthread_exit(NULL); 

} 


void *reader(void *arg) { 
    int *id = (int *) arg; 

    sleep(rand() % WAIT); 

    while(1) { 
     if (readerCount == NEW) { 
      sem_wait(&mutex); 

      v = version; 
      readerCount++; 

      if (readerCount == 1) 
       sem_wait(&access_data); 

      sem_post(&mutex); 

      fprintf(stderr, "Reader %d accessed the data\n", *id); 

      sem_wait(&mutex); 

      readerCount--; 

      if(readerCount == NEW) 
       sem_post(&access_data); 

      sem_post(&mutex); 

      pthread_exit(NULL); 
     } 
    } 

} 


int main() { 
    int numReaders = rand(); 
    int numWriters = rand(); 
    int i; 

    sem_init(&mutex, COMMON, VALUE); 
    sem_init(&access_data, COMMON, VALUE); 

    pthread_t readers[numReaders]; 
    pthread_t writers[numWriters]; 

    int readerID[numReaders]; 
    int writerID[numWriters]; 

    for (i = 0; i < numReaders; i++) 
     readerID[i] = i; 

    for (i = 0; i < numWriters; i++) 
     writerID[i] = i; 

    for (i = 0; i < numReaders; i++) { 
     if(pthread_create(&readers[i], NULL, reader, (void *) &readerID[i]) != 0) { 
      printf("Child failed\n"); 
      exit(EXIT_FAILURE); 
     } 
    } 

    for (i = 0; i < numWriters; i++) { 
     if (pthread_create(&writers[i], NULL, writer, (void *) &writerID[i]) != 0) { 
      printf("Child failed\n"); 
      exit(EXIT_FAILURE); 
     } 
    } 

    for (i = 0; i < numReaders; i++) { 
     if (pthread_join(readers[i], NULL) != 0) { 
      printf("Join failed\n"); 
      exit(EXIT_FAILURE); 
     } 
    } 

    for (i = 0; i < numWriters; i++) { 
     if (pthread_join(writers[i], NULL) != 0) { 
      printf("Join failed\n"); 
      exit(EXIT_FAILURE); 
     } 
    } 

    sem_destroy(&access_data); 
    sem_destroy(&mutex); 
} 
+3

'rand()'はかなりの数を返すことができます。それでも、あなたのスレッド数と配列サイジングには何を使用しているのでしょうか?おそらく、床の値が0より大きく、8より小さいなど、正気に制限するべきです。また、fyiではスレッドで 'rand()'を使うこともできます。スレッドセーフではないことはよく知られています。 – WhozCraig

答えて

1

セグメンテーションフォールトなしで実行してください。

0

容疑者:。!pthread_join(readers[i], NULL)

pthread_joinをする2番目の引数はへVARの有効なアドレスでなければなりませんこの場合、子スレッドが終了すると、pthread_exitはNULLにNULLを書き込もうとしますが、これはcaであると思いますsegフォルトを使用します。読者と書き込みの両方のためにpthread_joinの有効なアドレスにNULLを変更し、それが動作するかどうか確認してください。

EDIT:POSIXではpthread_joinにNULLを渡すことができます(下記のコメントを参照)ので、suspectは無罪です。

int numReaders = rand(); 
    int numWriters = rand(); 

Iを:あなたはちょうどここにランドを使用するのではなく、ある有限の値を割り当てる場合@WhozCraig

でコメントで示されるように、ランドは大きな数を返す場合、スタック領域が不足する可能性がある

+0

['pthread_join()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html)のPOSIX仕様では、2番目の引数をNULLポインタにすることができます。この場合、値は返されません。その使用は許されます。 –

+0

ありがとう@JonathanLefflerあなたは正しいです。 RAND_MAX> PTHREAD_THREADS_MAXなので、pthread_createはフォールトしていますか? –

関連する問題