2017-08-10 4 views
0

J'essaie d'implémenter une variante du problème de lecteurs et d'écrivains en C, la différence étant que les rédacteurs peuvent être soit des incrementers, soit des décrementers, et ils devraient garder un compte courant. Ci-dessous le code que j'essaie de mettre en œuvre, je reçois l'erreur "Segmentation Fault (core dumped) .J'ai essayé de déboguer et reçu cette rétroaction de gdb - # 0 0x0000000000400d84 dans main(). Je l'apprécierais si quelqu'un a pu expliquer cela me/me donner des conseils sur la façon de corriger ce défaut MerciC Segmentation Fault - lecteurs et écrivains

#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()' peut renvoyer un nombre important. Pourtant, c'est ce que vous utilisez pour votre nombre de threads et de dimensionnement de tableau, ce qui est franchement fou. Vous devriez peut-être limiter cela à quelque chose de sain, y compris une valeur floor> 0 et moins que, disons, 8. Et fyi, vous utilisez aussi 'rand()' sur vos threads, et notoirement * pas * thread-safe. – WhozCraig

Répondre

1

Vous êtes susceptible de manquer d'espace de pile si rand retourne grand nombre comme indiqué dans les commentaires par @WhozCraig

Si vous venez d'attribuer des valeurs finies au lieu d'utiliser rand ici:

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

I voir courir sans défaut de segmentation

0

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

Le second argument de pthread_join doit être une adresse valide d'un var contient l'adresse de la valeur renvoyée par les threads fils sortants Dans ce cas, quand un thread fils se termine, pthread_exit essaie d'écrire NULL à NULL, et je pense que ca est ca en utilisant le défaut de seg. Essayez de changer NULL à une adresse valide dans pthread_join pour les lecteurs et les écritures et voir si cela fonctionne.

EDIT: il s'avère que POSIX permet de passer NULL à pthread_join (voir les commentaires ci-dessous), donc suspect est acquitté.

+0

La spécification POSIX pour ['pthread_join()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html) permet au second argument d'être un pointeur nul, auquel cas aucune valeur n'est renvoyée . Cet usage est permis. –

+0

Merci @JonathanLeffler vous avez raison. Se pourrait-il que RAND_MAX> PTHREAD_THREADS_MAX, et donc pthread_create est en faute? –