【问题标题】:segmentation fault pushing back to vector in shared memory分段错误推回共享内存中的向量
【发布时间】:2021-02-19 14:09:37
【问题描述】:

我正在开发一个模拟旅行社预订航班的程序。它为每个代理启动一个进程,并针对共享内存中保存的 Plane 对象数组工作。

当我尝试将一排座椅推回飞机时,我遇到了分段错误。解析输入文件的方法在Plane 对象上调用SetSeats() 方法。每个Plane 包含一个vector<map<char, Seat>>(向量的每个索引是一行,每个映射的每个键都是该行上一个座位的字母)。当我打电话给SetSeats() 时,可以通过在第一张地图上添加座位,即第一排座位。当我尝试将地图推回座位向量时,它会引发段错误。

我在网上看到一些关于将自定义类推回需要解构器的向量,所以我将它们添加到 Seat.h 和 Plane.h。

主程序代码:

#include <iostream>
#include <map>
#include <vector>
#incluce <string>
#include <fstream>

#include "Seat.h"
#include "Plane.h"

void ParseInputFile(ifstream &inFS, int numPlanes, int &numAgents);
int shmid;
int *timer;
int numPlanes, numAgents;
struct sembuf *ops;
Plane *sharedPlanes;
map<string, Plane*> planes;

using namespace std;

int main(int argc, char *argv[])
{
  ifstream inFS;
  // code to get an input file from command line arguments and get number of planes from it

  // set up shared memory segment
  long key = XXX; // just a long integer
  int nbytes = 1024;
  shmid = shmget((key_t)key, nbytes, 0666 | IPC_CREAT);
  if (shmid == -1)
  {
    printf("Error in shared memory region setup.\n");
    perror("REASON");

    exit(2);
  }

  // initialize global variables
  sharedPlanes = new Plane[numPlanes];
  timer = new int;
  ops = new sembuf[1];

  // attached shared pointers to shared memory segment
  sharedPlanes = (Plane*)shmat(shmid, (Plane*)0, 0);
  timer = (int*)shmat(shmid, (int*)0, 0);
  *timer = 0;

  inFS.open(inputFile);

  ParseInputFile(inFS, numPlanes, numAgents); // breaks in here
 
  // the rest of main()
}

void ParseInputFile(ifstream &inFS, int numPlanes, int &numAgents)
{
  string line = "";

    bool foundNumberOfPlanes = false;
    bool foundPlanes = false;
    bool foundNumberOfAgents = false;
    bool lookingForAgent = false;
    bool foundAgent = false;
    
    int planeNo = 0;
    int agentNo = 0;
    int opNo = 0;

    map<string, Operation> ops;
    vector<Request> agentRequests;

    while (getline(inFS, line))
    {
        if (!CommonMethods::IsWhitespace(line))
        {
            // code to read first line

            if (foundNumberOfPlanes && !foundPlanes)
            {
                // parse a line from the input file to get details about the plane

                Plane *plane = &sharedPlanes[planeNo];

                unsigned int rows = xxx; // set based on the plane details
                unsigned int seatsPerRow = xxx; set based on the plane details

                plane->SetSeats(rows, seatsPerRow); // this is the method where I get the seg fault

                // finish defining the plane

                continue;

                // the rest of the method
            }
        }
    }
}

Plane.h 的代码:

#pragma once

#include <iostream>
#include <string>
#include <map>
#include <tuple>
#include <vector>

#include "Seat.h"
#include "Exceptions.h"
#include "ReservationStatus.h"
#include "CommonMethods.h"

using namespace std;

class Plane
{
    private:        
        vector<map<char, Seat>> seats;
        unsigned int numberOfRows, numberOfSeatsPerRow;
    public:
        Plane(unsigned int numberOfRows, unsigned int numberOfSeatsPerRow);
        Plane() {}
        void SetSeats(unsigned int numberOfRows, unsigned int numberOfSeatsPerRow);
};

void Plane::SetSeats(unsigned int numberOfRows, unsigned int numberOfSeatsPerRow)
{
    //cout << "Clearing old seats" << endl;
    if (!seats.empty())
    {
        //cout << "Seats not empty" << endl;
        
        for (int i = 0; i < (int)seats.size(); i++)
        {
            //cout << "checking row " << i << endl;

            if (!seats.at(i).empty())
            {
                //cout << "Row " << i << " not empty" << endl;

                seats.at(i).clear();
            }
        }
    }

    cout << "Rows: " << numberOfRows << ", Seats: " << numberOfSeatsPerRow << endl;

    this->numberOfRows = numberOfRows;
    this->numberOfSeatsPerRow = numberOfSeatsPerRow;

    for (unsigned int i = 0; i < this->numberOfRows; i++)
    {
        map<char, Seat> row;

        for (unsigned int j = 0; j < this->numberOfSeatsPerRow; j++)
        {
            Seat seat;
            seat.RowNumber = i + 1;
            seat.SeatLetter = j + 'A';

            //cout << "Inserting seat " << seat.RowNumber << seat.SeatLetter << endl;

            row.insert(pair<char, Seat>(seat.SeatLetter, seat));
        }

        if (!row.empty())
        {
            cout << "inserting row " << (i + 1) << endl;
            seats.push_back(row);
        }
    }
}

void Plane::ProcessWaitAny(int t)
{
    while (!WaitingList.empty())
    {
        bool booked = false;
        string pass = WaitingList.front();
        WaitingList.pop();

        for (unsigned int j = 0; j < numberOfRows; j++)
        {
            if (booked)
                break;

            for (unsigned int k = 0; k < numberOfSeatsPerRow; k++)
            {
                Seat *s = &seats.at(j)[k + 'A'];

                if (!s->IsBooked)
                {
                    Reserve(s, pass);
                    booked = true;

                    string seatNo = to_string(j);
                    seatNo += (k + 'A');

                    cout << "Passenger " << pass << " booked into seat " << seatNo << " at time " << t << endl;

                    break;
                }
            }
        }

        if (!booked)
            return;
    }
}

Seat.h 代码

#pragma once

#include <iostream>
#include <string>
#include <queue>

using namespace std;

struct Seat
{
    string Passenger = "";
    bool IsBooked = false;
    unsigned int RowNumber;
    char SeatLetter;
    queue<string> WaitingList;
};

【问题讨论】:

  • 无法编译,因为 Plane.h 需要的一些头文件丢失了
  • 它编译。我只在这里包含了我认为相关的内容,因为这已经是一篇很长的帖子了。
  • @dfoakley 不,您的示例没有编译。您的原始代码可能,但不是您在此问题中发布的代码。去掉不需要的#include 行,要么声明Plane::WaitingList,要么在~Plane() 中删除(毫无意义的)清除它。
  • 这个例子需要共享内存吗?如果你放弃那部分代码并依赖传统的内存管理,分段错误会消失吗?
  • 更新帖子以包含所有 Plane.h “// main() 的其余部分”中包含的部分通过 fork() 启动了几个子进程,它们都需要访问平面。使用共享内存是分配的要求。我还没有尝试删除它。

标签: c++ dictionary vector shared-memory


【解决方案1】:

我已经为您的问题做了一个最低限度的工作示例:

#include <vector>
#include <sys/shm.h>
#include <iostream>

class Bar {
public:
    Bar() {};
    std::vector<int> vec;
};

int main() {
  int shmid;
  Bar* a = new Bar();
  a->vec.push_back(1);
  // set up shared memory segment
  long key = 0x123455; // just a long integer
  int nbytes = 1024;
  shmid = shmget((key_t)key, nbytes, 0666 | IPC_CREAT);
  if (shmid == -1)
  {
    printf("Error in shared memory region setup.\n");
    perror("REASON");

    exit(2);
  }
  a = (Bar*)shmat(shmid, (Bar*)0, 0);

  a->vec.push_back(2);
}

问题是你错误地使用了shmat。指针sharedPlane 只是指向一些未初始化的共享内存。您必须确保key 提供的地址是“正确的”。为此,请执行以下操作:

  1. 您的其他进程,请致电Plane * other_process_sharedPlane = new Plane();。从主程序中删除 sharedPlanes = new Plane[numPlanes]; 行。
  2. 在您的主进程中,将key 设置为other_process_sharedPlane 的值
  3. 然后就可以调用shmget和shmadd了

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-17
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 1970-01-01
    相关资源
    最近更新 更多