C++:delete[] 错误,指针未分配
Posted
技术标签:
【中文标题】C++:delete[] 错误,指针未分配【英文标题】:C++: delete[] error, pointer not allocated 【发布时间】: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
可能会解决所有问题。
你可能犯了一个常见的错误,那就是先编写一大堆代码,然后运行它,看看它是否有效。但如果没有,你真的不知道问题可能出在哪里。专业程序员不会一下子写完所有东西,然后调试它。他们一次只编写几行代码,然后运行、测试、验证它是否有效,然后编写接下来的几行代码。首先编写一个简短的程序,分配一些对象,使用它们,然后delete
s 它们。一旦确保它正常工作,然后编写更多代码来创建更多对象等......
我已经问过我的助教,她不知道如何解决 -- 不用说,你有麻烦了。 -- 我读到每个 new[] 都应该与 delete[] 匹配,这就是我所拥有的 -- 如果您将源代码计算在内,是的,它们可能匹配。但它远不止数字匹配。但是,如果您的逻辑导致delete[]
的调用次数比new[]
的调用次数多怎么办?或者,如果您丢弃了 new[]
给您的指针值,而是删除了与 new[]
值不匹配的指针值?
请发minimal reproducible example,强调最小化。删除尽可能多的代码,直到找到重现问题的最少量代码,然后发布。
【参考方案1】:
您的代码存在许多问题,它们都可能以某种方式导致段错误。
补充@ShadowRanger 所指出的,sh
和sh2
是非动态分配的,dealer
保留对它们的引用。这两个对象在超出范围时会自动销毁。因此,当这种情况发生时,dealer
将对不再存在的对象进行操作,并且会出现分段错误。
我看到的分段错误的另一个原因是由于m_showrooms
在超出其容量时没有调整大小。 m_showrooms = new Showroom[m_maxCapacity];
行为Showroom
指针分配m_maxCapacity
的插槽数。当您调用AddShowroom
时,您需要检查是否会超出此容量。如果是这样,您需要分配一个更大的数组,将对象移过来,然后销毁旧数组(而不是它所容纳的对象)。
据我所知,您似乎不熟悉 C++ 中如何处理内存的想法。我建议花时间弄清楚这一点,因为它会为您省去很多麻烦。
【讨论】:
【参考方案2】:这些行保证内存泄漏:
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[]
ing 指针引起的。没有明显的代码这样做,但您没有提供MCVE(您提供的既不是最小的也不是完整的),所以它可能被隐藏了。
【讨论】:
感谢您的反馈。我想我真的需要回顾一下指针等背后的基本概念。虽然这并不能真正为我提供答案,但我接受了它,因为我认为让这个问题保持开放是没有效率的。以上是关于C++:delete[] 错误,指针未分配的主要内容,如果未能解决你的问题,请参考以下文章