我正在尝试在 C 中实现读取器和写入器问题的变体,变体是编写器可以是增量器或递减器,它们应该保持运行计数。下面是我尝试实现的代码,我收到错误"分段错误(核心转储(。我尝试调试并从 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 datan", *iID);
total++;
fprintf(stderr, "Total: %dn", total);
}
else {
fprintf(stderr, "Decrementer %d accessed the datan", *dID);
total--;
fprintf(stderr, "Total: %dn", 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 datan", *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 failedn");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < numWriters; i++) {
if (pthread_create(&writers[i], NULL, writer, (void *) &writerID[i]) != 0) {
printf("Child failedn");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < numReaders; i++) {
if (pthread_join(readers[i], NULL) != 0) {
printf("Join failedn");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < numWriters; i++) {
if (pthread_join(writers[i], NULL) != 0) {
printf("Join failedn");
exit(EXIT_FAILURE);
}
}
sem_destroy(&access_data);
sem_destroy(&mutex);
}
如果 rand 返回大数字,您可能会耗尽堆栈空间,如注释中所示 @WhozCraig
如果您只是分配一些有限值而不是在此处使用 rand:
int numReaders = rand();
int numWriters = rand();
我看到它运行而没有分段错误
嫌疑人:pthread_join(readers[i], NULL)
要pthread_join的第二个参数应该是 var 的有效地址,以包含来自现有子线程的返回值的地址。在这种情况下,当子线程退出时,pthread_exit尝试在 NULL 处写入 NULL,我认为这会导致 seg 错误。尝试将 NULL 更改为pthread_join中读取器和写入的某个有效地址,看看它是否有效。
编辑:事实证明,POSIX允许将NULL传递给pthread_join(见下面的评论(,因此嫌疑人被无罪释放。