2017-08-10 32 views
0

我試圖在C中實現讀者和作者問題的變體,變體是作者可以是增量或減量,他們應該保持運行計數。下面是我試圖實現的代碼,我得到錯誤「Segmentation Fault(核心轉儲)。我試圖調試,並收到來自gdb - #0 0x0000000000400d84在main()中的反饋。 我會感激如果有人能解釋這個給我/給我如何解決這個故障提示 感謝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的值。而且,你也可以在你的線程上使用rand(),並且它是非常安全的。 – WhozCraig

回答

1

你可能會耗盡堆棧空間,如果由@WhozCraig

在評論中指出如果你只是分配一些有限值,而不是在這裏使用蘭特蘭特返回大數目:

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

我看到它運行沒有分段錯誤

0

可疑:!pthread_join(readers[i], NULL)

的第二個參數在pthread_join應該是一個變種的有效地址包含來自退出子線程的返回值的地址在這種情況下,當一個子線程退出時,pthread_exit嘗試在NULL處寫NULL,並且我認爲這是ca使用seg故障。嘗試將NULL更改爲pthread_join中的某個有效地址,以供讀者和寫入者使用,並查看其是否有效。

編輯:事實證明,POSIX允許傳遞NULL到pthread_join(見下面的評論),所以犯罪嫌疑人被宣告無罪。

+0

['pthread_join()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html)的POSIX規範允許第二個參數爲空指針,在這種情況下,不返回任何值。這種用法是允許的。 –

+0

謝謝@JonathanLeffler你是對的。難道是RAND_MAX> PTHREAD_THREADS_MAX,所以pthread_create是錯誤的? –