【发布时间】:2018-09-07 00:01:03
【问题描述】:
我正在为一个实验室开发一个程序,我需要一些有关内存管理的帮助。作为一个整体,我是 C++ 新手,虽然我有其他语言的经验,但动态内存管理让我感到困惑。另外,因为这是针对实验室的,所以我不能使用 std::vector 或智能指针,只能使用数组和指针。
首先,有一个“Vehicle”类,其中包含一些描述它的属性(例如品牌、型号等)。接下来,有一个“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[] 匹配,这就是我所拥有的。我已经问过我的 TA,她不知道如何解决。
编辑:以下是一些相关代码:
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++;
}
【问题讨论】:
-
显示您的代码,而不是冗长的解释。听起来您确实没有正确删除数组(或者可能尝试删除它们两次)。
-
请提供您的代码。我的随机猜测是您不关注The Rule of Three,而是复制您的对象。如果您被允许并且已经了解它,
std::unique_ptr可能会解决所有问题。 -
你可能犯了一个常见的错误,那就是先编写一大堆代码,然后运行它,看看它是否有效。但如果没有,你真的不知道问题可能出在哪里。专业程序员不会一下子写完所有东西,然后调试它。他们一次只编写几行代码,然后运行、测试、验证它是否有效,然后编写接下来的几行代码。首先编写一个简短的程序,分配一些对象,使用它们,然后
deletes 它们。一旦确保它正常工作,然后编写更多代码来创建更多对象等...... -
我已经问过我的助教,她不知道如何解决 -- 不用说,你有麻烦了。 -- 我读到每个 new[] 都应该与 delete[] 匹配,这就是我所拥有的 -- 如果您将源代码计算在内,是的,它们可能匹配。但它远不止数字匹配。但是,如果您的逻辑导致
delete[]的调用次数比new[]的调用次数多怎么办?或者,如果您丢弃了new[]给您的指针值,而是删除了与new[]值不匹配的指针值? -
请发minimal reproducible example,强调最小化。删除尽可能多的代码,直到找到重现问题的最少量代码,然后发布。
标签: c++ pointers memory-management