我正在为一个实验室开发一个程序,我需要一些内存管理方面的帮助。我是C ++的新手,虽然我有其他语言的经验,但动态内存管理让我感到困惑。另外,因为这是针对实验室的,所以我不能使用std :: vector或智能指针,只能使用数组和指针。
首先,有一个“Vehicle”类,有一些描述它的属性(比如make,model等)。接下来,有一个“Showroom”类,其中包含一系列车辆:
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++;
}
这些行保证内存泄漏:
m_vehicles[i] = *new Vehicle(s.m_vehicles[i]);
和:
m_showrooms[i] = *new Showroom(d.m_showrooms[i]);
这是动态分配,解除引用和使用解除引用的值来将赋值复制到数组中。但是指向原始动态分配值的指针会立即丢失;你分配它的瞬间泄漏了内存。
你真的想要:
m_vehicles[i] = Vehicle(s.m_vehicles[i]);
和:
m_showrooms[i] = Showroom(d.m_showrooms[i]);
由于显而易见的原因,您的segfaulting代码出错了:
Dealership dealer("dealer", 1);
声称最多会分配一个陈列室,然后你两次调用AddShowroom
,并注销已分配内存的末尾(可能会破坏堆,谁知道还有什么)。
我不能肯定地说它为什么抱怨未分配的指针,但是你有很多泄漏和出界的错误,你的代码被遗漏了很多,很难说我没有' t错过了什么,与错误的代码是没有检查。您遇到的那种错误可能是由于堆损坏(您肯定会在不同时间造成的)或双重delete[]
ing指针引起的。没有明显的代码这样做,但你没有提供MCVE(你提供的既不是最小也不完整),所以它可能是隐藏的。
您的代码存在许多问题,并且它们都可能以某种方式导致段错误。
要添加@ShadowRanger指出的内容,sh
和sh2
不会动态分配,而dealer
会保留对它们的引用。当这两个对象超出范围时会自动销毁。因此,当发生这种情况时,dealer
将对不再存在的对象进行操作,并且随后会出现分段错误。
我看到分段错误的另一个原因是由于m_showrooms
在超出容量时没有调整大小。线m_showrooms = new Showroom[m_maxCapacity];
为m_maxCapacity
指针分配Showroom
槽数。当你打电话给AddShowroom
时,你需要检查是否会超过这个容量。如果是这样,你需要分配一个更大的数组,移动对象,然后销毁旧数组(而不是它所包含的对象)。
据我所知,您似乎不熟悉C ++中如何处理内存的想法。我建议花时间去弄清楚这一点,因为它会为你节省很多麻烦。