C ++:delete []错误,未分配指针

时间:2018-09-07 00:01:03

标签: c++ pointers memory-management

我正在为实验室编写程序,我需要一些有关内存管理的帮助。我是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++;
}

2 个答案:

答案 0 :(得分:1)

您的代码有很多问题,它们都可能以一种或另一种方式导致段错误。

要添加到@ShadowRanger指出的内容中,不会动态分配shsh2,并且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(您提供的内容既非最小也非完整),因此它可能是隐藏的。