Ошибка сегментации (дамп ядра) Проблема с первым считывателем-записью

#c #segmentation-fault #readerwriterlock

#c #ошибка сегментации #readerwriterlock

Вопрос:

 #include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>

int sleepval = 10, read_num = 0;
int readcnt = 0, writecnt = 0;
pthread_mutex_t mutex;
sem_t rw_mutex;

int randomGenerator(int high, int low){
    srand(time(0));
    return((rand() % (high - low   1))   100);
}

void *reader(void *readno){
    pthread_mutex_lock(amp;mutex);
    read_num  ;
    /* Block the writer if this is the first reader */
    if(read_num == 1){
        sem_wait(amp;rw_mutex);
    }
    pthread_mutex_unlock(amp;mutex);
    /* Read sleepval value and print */
    printf("Reader d reads %dn", *((int *)readno), sleepval);
    readcnt  ;
    sleep(sleepval / 1000);
    pthread_mutex_lock(amp;mutex);
    read_num--;
    /*Wake up writer if this is the last reader */
    if(read_num == 0){
        sem_post(amp;rw_mutex);
    }
    pthread_mutex_unlock(amp;mutex);
    int num = randomGenerator(500, 100);
    sleep(num / 1000);
}

void *writer(void *writeno){
    int num = randomGenerator(1000, 100);
    sleep(num / 1000);
    num = randomGenerator(50, 10);
    sem_wait(amp;rw_mutex);
    sleepval = num;
    printf("Writer d writes amp;dn", *((int*)writeno), sleepval);
    writecnt  ;
    sleep(sleepval / 1000);
    sem_post(amp;rw_mutex);
}

int main(int argc, char *argv[]){
    int r = atoi(argv[1]);
    int w = atoi(argv[2]);
    int second = 0;
    int i, id[100];
    if(r < 1 || r > 100 || w < 1 || w > 10){
        fprintf(stderr, "Usage: readwrite [read](1 - 100) [write](1 - 10)n");
        exit(-1);
    }
    
    pthread_t read[100], write[10];
    pthread_mutex_init(amp;mutex, NULL);
    sem_init(amp;rw_mutex, 0 , 1);

    /* Create threads for readers */
    for(i = 0; i < r; i  ){
        id[i] = i;
        pthread_create(amp;read[i], NULL, (void *)reader, (void *)amp;id[i]);
    }
    /* Create threads for writers */
    for(i = 0; i < w; i  ){
        id[i] = i;
        pthread_create(amp;write[i], NULL, (void *)writer, (void *)amp;id[i]);
    }

    sleep(30); //wait for 30 seconds

    /* Signal threads to finish */
    for (i = 0; i < r; i  ){
        pthread_join(read[i], NULL);
    }
    for (i = 0; i < w; i  ){
        pthread_join(write[i], NULL);
    }

    /* Display number of occurred reads and writes */
    printf("n==============================n");
    printf("Number of reads  :tdn", readcnt);
    printf("Number of writes :tdn", writecnt);

    pthread_mutex_destroy(amp;mutex);
    sem_destroy(amp;rw_mutex);

    return 0;
}
 

Это задание предназначено для решения первой проблемы чтения-записи. Я мог бы скомпилировать его в Linux, используя gcc -lpthread -lrt. Но когда я пытаюсь запустить его, используя заданный формат readwrtie 100 10, я получил ошибку сегментации (дамп ядра), и я не знаю почему. Я попытался запустить valgrind a.out, чтобы увидеть проблему, и я не мог понять. Пожалуйста, помогите мне.

Memcheck, детектор ошибок памяти

==19787== Авторское право (C) 2002-2012 и GNU GPL’d, Джулиан Сьюард и др.

==19787== Использование Valgrind-3.8.1 и LibVEX; повторите с помощью -h для получения информации об авторских правах

==19787== Команда: a.out

==19787==

== 19787 == Недопустимое чтение размера 1

==19787== при 0x57E7AC: ____strtol_l_internal (в /lib/libc-2.12.so)

==19787== по 0x57E50F: strtol (в /lib/libc-2.12.so)

==19787== по 0x57AEB0: atoi (в /lib/libc-2.12.so)

==19787== по 0x8048A32: main (in /gaia/class/student/maih/maih-asgmt3/a.out)

== 19787== Адрес 0x0 не является стеком, malloc или (недавно) свободным

==19787==

==19787==

==19787== Процесс завершается действием сигнала 11 по умолчанию (SIGSEGV)

== 19787 == Доступ не в пределах отображенной области по адресу 0x0

==19787== при 0x57E7AC: ____strtol_l_internal (в /lib/libc-2.12.so)

==19787== по 0x57E50F: strtol (в /lib/libc-2.12.so)

==19787== по 0x57AEB0: atoi (в /lib/libc-2.12.so)

==19787== по 0x8048A32: main (in /gaia/class/student/maih/maih-asgmt3/a.out)

== 19787 == Если вы считаете, что это произошло в результате стека

== 19787 == переполнение в основном потоке вашей программы (маловероятно, но

== 19787 == возможно), вы можете попытаться увеличить размер

== 19787== основной стек потоков с использованием флага —main-stacksize= .

== 19787== Размер стека основного потока, используемый в этом запуске, составлял 10485760.

==19787==

== 19787 == СВОДКА КУЧИ:

== 19787 == используется при выходе: 0 байт в 0 блоках

== 19787 == общее использование кучи: 0 выделений, 0 освобождений, 0 выделенных байтов

==19787==

==19787 == Все блоки кучи были освобождены — утечки невозможны

==19787==

==19787== Для подсчета обнаруженных и подавленных ошибок выполните повторный запуск с помощью: -v

== 19787 == СВОДКА ОШИБОК: 1 ошибка из 1 контекста (подавлено: 13 из 8)

Ошибка сегментации (сброс ядра)

Комментарии:

1. «использование заданного формата readwrtie 100 10». Что именно это значит? Пожалуйста, покажите точную команду, которую вы выполняете. Трассировка стека предполагает, что некоторые программные аргументы могут отсутствовать. Кроме того, добавьте код для проверки argc перед доступом к любой из argv записей.

2. Кроме того, в этом случае отладчик был бы более полезен, чем valgrind. Программа будет взломана в отладчике, когда произойдет ошибка сегментации, и затем вы можете проверить переменные, в частности argv , и argc .

Ответ №1:

В вашей функции записи измените

 printf("Writer d writes amp;dn", *((int*)writeno), sleepval);
---------------------------^
 

Для

 printf("Writer d writes %dn", *((int*)writeno), sleepval);
---------------------------^
 

В вашей основной функции измените

 pthread_create(amp;read[i], NULL, (void *)reader, (void *)amp;id[i]);
pthread_create(amp;write[i], NULL, (void *)writer, (void *)amp;id[i]);
 

Для

 pthread_create(amp;read[i], NULL, reader, amp;id[i]);
pthread_create(amp;write[i], NULL, writer, amp;id[i]);
 

Добавьте оператор return в функцию чтения и записи.
Удалите неиспользуемую переменную second в функции main.

Повторите попытку.