Ошибка Seg в программе производителя-потребителя

Я изучал параллельное программирование, реализуя проблему производителя-потребителя. В коде есть только один производитель и один потребитель. Потребительский поток находится в цикле while, заблокированном на пустом семафоре. Код генерирует segfault 11, который я не могу отлаживать. Я попытался удалить цикл while в потребительском потоке, после чего я не вижу segfault, почему это?

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <queue>
#include <unistd.h>
#include <semaphore.h>
using namespace std;

queue<int> buff;
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
sem_t empty;

void producer(int i){

   pthread_mutex_lock(&mut);
   buff.push(i);
   sem_post(&empty);
   pthread_mutex_unlock(&mut);

}

void* produce_data(void* arg){
    for(int i = 5 ; i < 10 ; i++){
        producer(i);
    }

   return NULL;
}

void* consumer(void* arg){

    while(1){
        sem_wait(&empty);
        pthread_mutex_lock(&mut);
        int temp = buff.front();
        cout << temp <<" " ;
        buff.pop();
        pthread_mutex_unlock(&mut);
     }

    return 0;
}

int main () {
   pthread_t prod;
   sem_init(&empty, 0, 0);
   pthread_create(&prod, NULL, produce_data , NULL);

   pthread_t consum2;

   pthread_create(&consum2, NULL,consumer , NULL);

   pthread_join(prod,NULL);

   pthread_join(consum2,NULL);


   return 0;

}

person Punit Salian    schedule 09.03.2020    source источник
comment
Можете ли вы объяснить, что именно делает вас неспособным отлаживать эту простую программу?   -  person Sam Varshavchik    schedule 09.03.2020
comment
переместите sem_post за пределы мьютекса.   -  person stark    schedule 09.03.2020
comment
Я пытался распечатать кое-что, но не помогло. Как и в случае с потребителем, я просто выталкиваю очередь, а затем сплю на семафоре, я не уверен, как я могу получить доступ к недопустимой памяти здесь   -  person Punit Salian    schedule 09.03.2020
comment
@stark не помог вынести sem_post наружу   -  person Punit Salian    schedule 09.03.2020
comment
Невозможно воспроизвести. Добавление кода для сброса cout приводит к ожидаемому результату, за которым следует зависание, поскольку один поток находится в pthread_join, а другой — в бесконечном цикле while.   -  person David Schwartz    schedule 09.03.2020
comment
Вы пробовали проверять ошибки? Может быть, начать с функций sem; например, если (sem_init(&пусто, 0, 0)) { perror(sem_init); }; затем перейдите к мьютексам, посмотрите, не выскочит ли что-нибудь.   -  person mevets    schedule 09.03.2020
comment
@DavidSchwartz, это немного помогло, теперь я вижу 5 6 7 0 0 0 0 0 0 .... много нулей, а затем ошибка сегмента 11   -  person Punit Salian    schedule 09.03.2020
comment
@DavidSchwartz, кажется, работает сброс cout! Какое объяснение этому?   -  person Punit Salian    schedule 09.03.2020
comment
@PunitSalian Я не могу создать segfault из вашего кода, как бы я ни пытался. Я не понимаю, почему ваш код будет ошибаться, если только опубликованный код не является правильным кодом. Вы на 100 % уверены, что точный код, которым вы поделились в своем вопросе, приводит к segfault?   -  person David Schwartz    schedule 09.03.2020
comment
@DavidSchwartz Да, Дэвид, это точно такой же код. Я использую g++ на Mac и все равно получаю segfault, но попытался выполнить то же самое в онлайн-компиляторе, я получаю ожидаемый результат с сбросом на cout. Моя версия MAC g++ настроена с помощью: --prefix=/Library/Developer/ CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM версии 10.0.0 (clang-1000.10.44.4) Цель: x86_64-apple-darwin17.7.0 Модель потока posix InstalledDir: /Библиотека/Разработчик/CommandLineTools/usr/bin   -  person Punit Salian    schedule 09.03.2020
comment
@PunitSalian Требуется ли вашему компилятору -pthread или что-то подобное для компиляции кода, использующего стандарт pthreads?   -  person David Schwartz    schedule 09.03.2020
comment
@DavidSchwartz Нет ничего как такового, просто скомпилируйте: g++ prod_consumer.cc -o prod.o без привязки pthread   -  person Punit Salian    schedule 09.03.2020


Ответы (1)


Sem_init() устарела в macos. Компиляция вашей программы должна была показать это. Кроме того, если бы вы проверили возвращаемые значения, вы бы знали, что все sem_init(), sem_post(), sem_wait() не работают. По какой-то причине из вашей очереди появляется около 1023 сообщений, и это SEGV.

person mevets    schedule 09.03.2020