2017-08-10 55 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是错误的? –