Сегментация неисправных потоков - PullRequest
0 голосов
/ 04 ноября 2019

Я написал этот код, который имитирует систему парковки, однако у меня возникает проблема, когда мне приходится повторно использовать структуру, содержащую messageQueue, для моей корзины. Проблема возникает, когда я пытаюсь связаться с обработчиком для выхода с ID_CAR_IND. Структура отправляется как сообщение, поэтому я подозреваю, что оно удаляется до прибытия, но я не могу понять, что происходит, и где оно идет не так. Следует отметить, что реализация требования - использование pthread и создание 3 потоков.

#include <iostream>
#include <pthread.h>
#include <stdlib.h>
#include <queue>
#include <time.h>
#include <unistd.h>
#include "Message.h"
#include "MsgQueue.h"


using namespace std;

enum{
    ID_START_IND,
    ID_ENTRY_REQ,
    ID_ENTRY_CFM,
    ID_CAR_IND,
    ID_STAY_HERE,
    ID_EXIT_REQ,
    ID_EXIT_OUT,
    ID_EXIT_CFM
    };

//MESSAGES
struct Car : public Message
{
    Car(int carID, MsgQueue* queue) : id(carID), carmq(queue){}
    MsgQueue *carmq;
    int id;
};

struct OpenReq : public Message
{
    MsgQueue *Who_is_asking_;
};

struct CloseReq : public Message
{
    MsgQueue *Who_is_asking_exit;
};

struct EntryDoorOpen : public Message{
    bool result;
};


MsgQueue entryMq(20);
MsgQueue exitMq(20);

void carHandler(Car* car, unsigned id, Message* msg){
    switch(id){
        case ID_START_IND:
        {
            cout << "car " << car->id << " wants to enter" << endl;
            OpenReq * req = new OpenReq();
            req->Who_is_asking_ = car->carmq;
            entryMq.send(ID_ENTRY_REQ, req);
        }
            break;

        case ID_ENTRY_CFM:
        {
            cout << "car " << car->id << " entered parking" << endl;
            entryMq.send(ID_CAR_IND);
        }
            break;

        case ID_STAY_HERE:
        {

        }
            break;

        case ID_EXIT_CFM:
        {
            cout << "car " << car->id << "Left parking" << endl;
            exitMq.send(ID_EXIT_OUT);
        }
            break;

        default:
            break;
    }
}

void entryHandler(unsigned id, Message* msg){

    OpenReq* req=static_cast<OpenReq*>(msg);

    switch(id){
        case ID_ENTRY_REQ:
        {
            cout << "Access granted. Opening entry door " << endl;

            req->Who_is_asking_->send(ID_ENTRY_CFM);
        }
            break;

        case ID_CAR_IND:
        {

            cout << "Closing entry door " << endl;
            sleep(2);
            req->Who_is_asking_->send(ID_EXIT_REQ);

        }
            break;

        default:
            break;
    }
}

void exitHandler(unsigned id, Message * msg)
{
    OpenReq* req = static_cast<OpenReq*>(msg);

    switch(id)
    {
        case ID_EXIT_REQ:
        {
            cout << "Leaving is Granted. Opening exit door" << endl;
            req->Who_is_asking_->send(ID_EXIT_CFM);
        }
            break;

        case ID_EXIT_OUT:
        {
            cout << "Car has left the parkinglot" << endl;
        }
            break;

        default:
            break;
    }
}

void *car(void* data){
    Car *car = static_cast<Car*>(data);
    car->carmq->send(ID_START_IND);
    for(;;){
        unsigned long id;
        Message *msg = car->carmq->receive(id);
        carHandler(car,id,msg);
        delete(msg);
    }
}

void *entry(void* data){
    for(;;){
        unsigned long id;
        Message *msg = entryMq.receive(id);
        entryHandler(id,msg);
        delete(msg);
    }
}

void *exit(void * data){
    for(;;){
        unsigned long id;
        Message *msg = exitMq.receive(id);
        exitHandler(id,msg);
        delete(msg);
    }

}


int main()
{
    MsgQueue q(10);

    Car carObj(1, &q);

    pthread_t carThread, entryThread;
    pthread_create(&carThread,nullptr,car, &carObj);
    pthread_create(&entryThread,nullptr,entry, nullptr);

    pthread_join(carThread,nullptr);


    return 0;
}
//
// Created by stud on 11/3/19.
//

#include "MsgQueue.h"
#include "Message.h"
#include <iostream>


MsgQueue::MsgQueue(unsigned long maxSize) : maxSize_(maxSize)
{
    //Init pthread funktionerne.
    pthread_mutex_init(&msgmutex, NULL);
    pthread_cond_init(&msgcond,NULL);
};

void MsgQueue::send(unsigned long id, Message* msg)
{
    pthread_mutex_lock(&msgmutex);

    while(msgqueue_.size() == maxSize_)
    {
        pthread_cond_wait(&msgcond, &msgmutex);
    }

    info besked;
    besked.id = id;
    besked.msg = msg;

    msgqueue_.push(besked);

    pthread_cond_broadcast(&msgcond);
    pthread_mutex_unlock(&msgmutex);

    //std::cout << "sending from id #" << id << std::endl;
};

Message* MsgQueue::receive(unsigned long&id)
{
    pthread_mutex_lock(&msgmutex);

    while(msgqueue_.empty())
    {
        pthread_cond_wait(&msgcond,&msgmutex);
    }
    info besked;

    besked = msgqueue_.front();
    id = besked.id;
    msgqueue_.pop();

    pthread_cond_broadcast(&msgcond);
    pthread_mutex_unlock(&msgmutex);

    return besked.msg;
};

MsgQueue::~MsgQueue()
{
    pthread_mutex_destroy(&msgmutex);
    pthread_cond_destroy(&msgcond);
};
//
// Created by stud on 11/3/19.
//

#pragma once

#include <iostream>
#include <pthread.h>
#include "Message.h"
#include <queue>

struct info : public Message
{
    unsigned long id;
    Message* msg;
};

class MsgQueue
{
public:
    MsgQueue(unsigned long maxSize);
    void send(unsigned long id, Message* msg = NULL);
    Message* receive(unsigned long&id);
    ~MsgQueue();

private:
    unsigned long maxSize_;
    std::queue <info> msgqueue_;
    pthread_cond_t msgcond;
    pthread_mutex_t msgmutex;
};
//
// 
//

#pragma once

class Message
{
public:
    virtual ~Message(){};
};

Ответы [ 2 ]

0 голосов
/ 04 ноября 2019

Подумайте о пересмотре кода для проверки или удаления последовательного использования оператора ->. Есть способ, которым код не может поймать значение null.

0 голосов
/ 04 ноября 2019

В настоящее время в вопросе отсутствуют некоторые детали (например, подробности о том, что именно представляет собой ваша проблема, включая любое полученное вами сообщение об ошибке), но мы можем предположить, что это за проблема. Поскольку проблема связана с ID_CAR_IND, давайте начнем с проверки обработчика этого сообщения. Он печатает сообщение, а затем разыменовывает указатель, который является свойством сообщения. Ничего, очевидно, не так.

Итак, давайте проверим, где мы создаем это сообщение. Он отправляет только идентификатор сообщения. Дальнейшие исследования показывают, что send принимает необязательный второй параметр. Поскольку оно не предоставлено, это будет nullptr в отправляемом сообщении.

Поскольку эти дополнительные данные сообщения необходимы обработчику сообщения и не предоставляются, это приводит к разыменованию нулевого указателя вобработчик, приводящий к неопределенному поведению и (как правило) к аварийному завершению программы с чем-то вроде ошибки нарушения доступа.

Решение состоит в том, чтобы передать объект OpenReq в send (как вы дляID_START_IND сообщение).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...