我正在为实验室编写程序,我需要一些有关内存管理的帮助。我是C ++整体的新手,虽然我有其他语言的经验,但是动态内存管理使我感到困惑。另外,因为这是一个实验,所以我不能使用std :: vector或智能指针,而不能使用数组和指针。
首先,有一个“车辆”类,其中描述了一些属性(例如品牌,型号等)。接下来,有一个“ Showroom”类,其中包含一系列Vehicles:
Vehicle * m_vehicles;
然后在构造函数中:
m_vehicles = new Vehicle[m_maxCapacity];
接下来是一个“经销商”类,其中包含一系列展示厅:
Showroom * m_showrooms;
...
m_showrooms = new Showroom[m_maxCapacity];
我的main()方法创建了一些车辆,将其添加到陈列室,然后将其添加到经销店。一切正常,直到程序结束。当程序完成并删除对象时,出现了一些问题。由于经销商是最后创建的,因此将其首先删除。它是析构函数调用delete[] m_showrooms;
,而Showroom类中的析构函数调用delete[] m_vehicles;
。因此,我希望程序结束时,操作系统会删除经销商对象,从而删除陈列室对象,从而又删除车辆对象。
但是,它不能正常工作。该实验室要求我们使用提供的帮助程序,该帮助程序将内存泄漏标记为错误。什么时候 我的main()创建了一个展示厅,向其中添加了车辆,创建了一个经销店,然后将展厅添加到经销店,当程序结束时,内存泄漏检测器给出了一个错误,说:
delete[] error: pointer was not allocated!
我添加到经销店的每个陈列室都收到一次此错误。另外,还有另一个奇怪的错误:如果经销商包含任何两个具有相同容量的陈列室,则该程序结束时会出现段错误。
如果我说“拧紧”并从析构函数中删除所有delete [],则程序运行时不会出现段错误,但内存泄漏程序会检测到泄漏并阻止我继续前进。
我在做什么错?我对C ++中的动态内存有某种基本的误解吗?我读到每个new []应该与delete []相匹配,这就是我所拥有的。我已经问过我的助教,她对此一无所知。
编辑:这是一些相关代码:
main.cpp:
//array of vehicles to store
Vehicle vehicles[] =
{
Vehicle("Ford", "Mustang", 1973, 9500, 113000),
Vehicle("Mazda", "CX-5", 2017, 24150, 5900),
Vehicle("Dodge", "Charger", 2016, 18955, 9018),
Vehicle("Telsa", "Model S", 2018, 74500, 31),
Vehicle("Toyota", "Prius", 2015, 17819, 22987),
Vehicle("Nissan", "Leaf", 2016, 12999, 16889),
Vehicle("Chevrolet", "Volt", 2015, 16994, 12558),
};
// Showrooms to store the vehicles
Showroom showroom("Primary Showroom",2);
showroom.AddVehicle(&vehicles[0]);
showroom.AddVehicle(&vehicles[1]);
//showroom.AddVehicle(&vehicles[2]);
Showroom secondary("Storeroom 2",4);
secondary.AddVehicle(&vehicles[3]);
secondary.AddVehicle(&vehicles[4]);
secondary.AddVehicle(&vehicles[5]);
secondary.AddVehicle(&vehicles[6]);
// A "parent" object to store the Showrooms
Dealership dealership("Dealership",2);
dealership.AddShowroom(&showroom);
dealership.AddShowroom(&secondary);
//displays the showrooms and their contents
dealership.ShowInventory();
Vehicle.cpp中的相关功能:
Vehicle::Vehicle(std::string mk, std::string md, int yr, int pr, int ml) {
make = mk;
model = md;
year = yr;
price = pr;
miles = ml;
}
Vehicle::~Vehicle() {}
Vehicle::Vehicle(const Vehicle &veh) {
//year = new int;
make = veh.make;
model = veh.model;
year = veh.year;
price = veh.price;
miles = veh.miles;
}
Vehicle& Vehicle::operator=(const Vehicle &veh) {
make = veh.make;
model = veh.model;
year = veh.year;
price = veh.price;
miles = veh.miles;
return *this;
}
Vehicle::Vehicle() {}
来自Showroom.cpp:
//copy constructor
Showroom::Showroom(const Showroom &s)
{
m_name = s.m_name;
m_maxCapacity =s.m_maxCapacity;
m_currentNumberOfVehicles = s.m_currentNumberOfVehicles;
m_vehicles = new Vehicle[m_maxCapacity];
for (int i = 0; i< s.m_currentNumberOfVehicles;i++)
{
m_vehicles[i] = *new Vehicle(s.m_vehicles[i]);
}
}
//normal constructor
Showroom::Showroom(std::string name, unsigned int maxCapacity) {
m_name = name;
m_maxCapacity = maxCapacity;
m_vehicles = new Vehicle[m_maxCapacity];
m_currentNumberOfVehicles = 0;
}
Showroom::~Showroom() {
delete[] m_vehicles;
}
Showroom::Showroom(){}
来自Dealership.cpp:
//copy constructor
Dealership::Dealership(const Dealership &d)
{
m_name = d.m_name;
m_maxCapacity =d.m_maxCapacity;
m_currentNumberOfShowrooms = d.m_currentNumberOfShowrooms;
m_showrooms = new Showroom[m_maxCapacity];
for (int i = 0; i< d.m_currentNumberOfShowrooms;i++)
{
m_showrooms[i] = *new Showroom(d.m_showrooms[i]);
}
}
//normal constructor
Dealership::Dealership(std::string name, unsigned int capacity) {
m_name = name;
m_maxCapacity = capacity;
m_currentNumberOfShowrooms = 0;
m_showrooms = new Showroom[m_maxCapacity];
}
Dealership::~Dealership() {
//std::cout<<"Deleting dealership " <<m_name << std::endl;
delete[] m_showrooms;
//m_showrooms = 0;
}
编辑2:这是main()中给出的最少的代码,错误提示我试图取消分配未分配的指针:
Showroom sh("Name", 0);
Dealership dealer("dealer", 1);
dealer.AddShowroom(&sh);
这是段错误的最少代码:
Showroom sh("Name", 0);
Showroom sh2("Showroom 2",0);
Dealership dealer("dealer", 2);
dealer.AddShowroom(&sh);
dealer.AddShowroom(&sh2);
这是AddShowroom(),以供参考:
void Dealership::AddShowroom(const Showroom *showroom) {
m_showrooms[m_currentNumberOfShowrooms] = *showroom;
m_currentNumberOfShowrooms++;
}
答案 0 :(得分:1)
您的代码有很多问题,它们都可能以一种或另一种方式导致段错误。
要添加到@ShadowRanger指出的内容中,不会动态分配sh
和sh2
,并且dealer
会保留对它们的引用。当这两个对象超出范围时,它们将自动销毁。因此,当发生这种情况时,dealer
将在不再存在的对象上运行,并且将发生分段错误。
我看到分段错误的另一个原因是由于m_showrooms
超出其容量时未调整大小。第m_showrooms = new Showroom[m_maxCapacity];
行为m_maxCapacity
指针分配了Showroom
个插槽。调用AddShowroom
时,您需要检查是否会超出此容量。如果是这样,则需要分配一个更大的数组,将对象移到上方,然后销毁旧数组(而不是其容纳的对象)。
据我所知,您似乎并不熟悉C ++中如何处理内存的想法。我建议您花点时间解决这个问题,因为这将为您省去很多麻烦。
答案 1 :(得分:0)
这些行可以保证内存泄漏:
m_vehicles[i] = *new Vehicle(s.m_vehicles[i]);
和:
m_showrooms[i] = *new Showroom(d.m_showrooms[i]);
这是动态分配,取消引用,并使用取消引用的值将assign复制到数组中。但是,立即丢失了指向原始动态分配值的指针;您在分配内存的那一刻就在泄漏内存。
您真的想要:
m_vehicles[i] = Vehicle(s.m_vehicles[i]);
和:
m_showrooms[i] = Showroom(d.m_showrooms[i]);
您的段错误代码出现错误的原因很明显:
Dealership dealer("dealer", 1);
最多将分配一个展示厅,然后您调用AddShowroom
两次,然后注销分配的内存的末尾(可能破坏堆,并且谁知道什么)。
我不能肯定地说为什么它抱怨未分配的指针,但是周围有很多泄漏和越界错误,并且省略了很多代码,所以很难确定我没有错过任何东西,而没有错误的代码则无法检查。您遇到的这类错误可能是由堆损坏(肯定在不同时间造成的)引起的,也可能是由两次delete[]
指向指针引起的。没有明显的代码正在执行此操作,但是您尚未提供MCVE(您提供的内容既非最小也非完整),因此它可能是隐藏的。