C分段错误 - 读者和作者

时间:2017-08-10 03:21:22

标签: c segmentation-fault pthreads semaphore readerwriterlock

我正在尝试在C中实现读者和作者问题的变体,变化是作者可以是增量者或减量者,他们应该保持运行计数。下面是我试图实现的代码,我收到错误“Segmentation Fault(core dumped)。我试图调试并从gdb收到这个反馈 - #0 0x0000000000400d84在main()中。 如果有人能够向我解释这个/给我一些如何解决这个错误的提示,我将不胜感激。 谢谢!

#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);
}

2 个答案:

答案 0 :(得分:1)

如果rand返回大号,你可能会用完堆栈空间,如@WhozCraig的评论所示

如果你只是在这里指定一些有限值而不是使用rand:

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

我看到它在没有分段错误的情况下运行

答案 1 :(得分:0)

怀疑:pthread_join(readers[i], NULL)

pthread_join的第二个参数应该是var的有效地址,以包含来自现有子线程的返回值的地址。在这种情况下,当子线程退出时,pthread_exit尝试在NULL处写入NULL,我认为这会导致seg错误。尝试将NULL更改为pthread_join中的某个有效地址,以便读取和写入,并查看它是否有效。

编辑:事实证明,POSIX允许将NULL传递给pthread_join(请参阅下面的评论),因此怀疑是无罪释放。