分段故障线程

问题描述 投票:-1回答:1

我已经编写了此代码来模拟停车系统,但是当我必须将包含messageQueue的结构重用到我的carthread时,我遇到了问题。当我尝试与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;
};

//
// Created by stud on 11/3/19.
//

#pragma once

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

c++ struct pthreads thread-synchronization
1个回答
0
投票

该问题目前缺少一些详细信息(例如有关您的问题到底是什么的详细信息,包括您收到的任何错误消息),但是我们可以推测出问题所在。由于问题出在ID_CAR_IND,因此让我们开始检查该消息的处理程序。它打印一条消息,然后取消引用作为该消息属性的指针。那里什么都没错。

所以让我们检查在哪里创建该消息。它仅发送消息ID。进一步的调查显示,send采用可选的第二个参数。由于未提供,因此它将是所发送消息中的nullptr

由于消息处理程序需要并没有提供这些额外的消息数据,所以这会导致在处理程序中取消引用空指针,从而导致未定义行为,并(通常)导致程序崩溃,并出现访问冲突错误。

解决方案是将OpenReq对象传递给send(就像处理ID_START_IND消息一样。]

© www.soinside.com 2019 - 2024. All rights reserved.