【发布时间】: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