2017-08-10 1 views
0

Ich versuche, eine Variation der Leser und Schreiber Problem in C zu implementieren, ist die Variation, die Autoren entweder Inkrementierern oder Dekrementierer sein können, und sie sollten eine laufende Zählung halten. . Unten ist der Code, den ich zu implementieren Ich versuche, ich den Fehler „Segmentation Fault (core dumped) bekommen habe ich zu debuggen versucht und erhielt dieses Feedback von GDB - # 0 0x0000000000400d84 in main() ich es schätzen würde, wenn. jemand konnte mir dies erklären/gib mir Tipps, wie diese Fehler zu beheben DankC Segmentation Fault - Leser und Schreiber

#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()' kann eine beträchtliche Zahl zurück. Aber das ist, was Sie für Ihre Thread-Anzahl und Array-Sizing verwenden, die offen gesagt verrückt ist. Vielleicht sollten Sie, dass beschränken bis auf etwas sane, einschließlich einer Bodenwert> 0 und kleiner als, sagen wir, 8. Und FYI, können Sie auch 'rand() verwenden' auf Fäden, und es ist notorisch * nicht * Thread-sicher. – WhozCraig

Antwort

1

Sie sind wahrscheinlich aus Stapelspeicherplatz laufen, wenn rand große Zahl zurückgibt, wie in den Kommentaren von @WhozCraig angegeben

Wenn Sie nur einige endliche Werte zuweisen, anstatt rand hier verwenden:

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

I sehen es läuft ohne Segmentation Fault

0

Suspect:.! pthread_join(readers[i], NULL)

Das zweite Argument eine gültige Adresse eines var zu pthread_join sein sollte In diesem Fall versucht pthread_exit, NULL bei NULL zu schreiben, und ich denke, das ist ca mit Seg-Fehler. Versuchen Sie, NULL zu einer gültigen Adresse in pthread_join für beide Leser und Schreibvorgänge zu ändern, und sehen Sie, ob es funktioniert.

EDIT: es stellt sich heraus, dass POSIX NULL pthread_join vorbei (siehe Kommentare unten) erlaubt, so wird Verdächtigen freigesprochen.

+0

Die POSIX-Spezifikation für [ 'pthread_join()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html) ermöglicht es das zweite Argument einen Zeiger auf null zu sein, wobei in diesem Fall kein Wert zurückgegeben wird, . Diese Verwendung ist zulässig. –

+0

Dank @ JonathanLeffler hast du Recht. Könnte es sein, dass RAND_MAX> PTHREAD_THREADS_MAX und so pthread_create fehlerhaft ist? –