分段错误线程

Segmentation fault threads

我已经编写了这段模拟停车系统的代码,但是当我必须将包含 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;
};
//
// 
//

#pragma once

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

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

那么让我们检查一下我们创建该消息的位置。它只发送消息 ID。进一步的调查表明 send 有一个可选的第二个参数。由于未提供,这将是发送的消息中的 nullptr

由于消息处理程序需要这个额外的消息数据,但没有提供,这会导致取消引用处理程序中的空指针,导致未定义的行为和(通常)程序崩溃,例如访问违规错误。

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

考虑修改代码以检查或删除 -> 运算符的连续使用。代码无法捕获 null 值的某些方式。

为什么不使用 OS API 而不是实现自己的 MsgQueue?