C ++: ошибка удаления [], указатель не выделен - PullRequest
0 голосов
/ 07 сентября 2018

Я работаю над программой для лаборатории, и мне нужна помощь с управлением памятью. Я новичок в C ++ в целом, и хотя у меня есть опыт работы с другими языками, динамическое управление памятью сбивает меня с толку. Кроме того, поскольку это для лаборатории, я не могу использовать std :: vector или интеллектуальные указатели, только массивы и указатели.

Во-первых, есть класс «Автомобиль», с некоторыми атрибутами, описывающими его (например, марка, модель и т. Д.). Далее есть класс «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;. Итак, я ожидаю, что когда программа завершится, ОС удалит объект автосалона, который удалит объекты автосалона, которые, в свою очередь, удалят объекты автомобиля.

Однако, это не работает должным образом. Лаборатория требует, чтобы мы использовали предоставленного помощника, который отмечает утечки памяти как ошибки. когда my main () создает шоу-рум, добавляет в него транспортные средства, создает дилерский центр, а затем добавляет шоу-рум в дилерский центр, когда программа завершает работу, детектор утечки памяти выдает ошибку, говоря:

delete[] error: pointer was not allocated!

Я получаю эту ошибку один раз за каждый выставочный зал, который добавляю в автосалон. Кроме того, есть еще одна странная ошибка: я получаю ошибку, когда программа заканчивается, если в автосалоне есть два выставочных зала одинаковой вместимости.

Если я скажу «привинтить» и удалить все delete [] из деструкторов, программа запустится без ошибки, но программа утечки памяти обнаружит утечку и не даст мне двигаться дальше.

Что я делаю не так? Есть ли у меня какое-то фундаментальное недопонимание динамической памяти в C ++? Я прочитал, что каждый новый [] должен совпадать с 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);

Вот наименьшее количество кода, которое segfaults:

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 голосов
/ 07 сентября 2018

Есть много проблем с вашим кодом, и все они могут так или иначе привести к ошибкам сегмента.

Чтобы добавить к тому, на что указал @ShadowRanger, sh и sh2 равны не выделяется динамически, а dealer хранит ссылку на них.Эти два объекта уничтожаются автоматически, когда они выходят за рамки видимости.Поэтому, когда это произойдет, dealer будет работать на объектах, которые больше не существуют, и возникнет ошибка сегментации.

Другая причина ошибки сегментации, которую я вижу, связана с тем, что m_showrooms не изменяется в размерах при превышении его емкости.Строка m_showrooms = new Showroom[m_maxCapacity]; выделяет m_maxCapacity количество слотов для Showroom указателей.Когда вы звоните AddShowroom, вам необходимо проверить, будет ли эта емкость превышена.Если это так, вам нужно выделить больший массив, переместить объекты, а затем уничтожить старый массив (а не объекты, в которых он размещается).

Из того, что я могу сказать, вы, похоже, не знакомы с идеейо том, как обрабатывается память в C ++.Я предлагаю потратить время, чтобы понять это, потому что это избавит вас от многих головных болей в будущем.

0 голосов
/ 07 сентября 2018

Эти строки гарантируют утечки памяти:

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 и списываете конец выделенной памяти (вероятно, это повредит кучи и кто знает, что еще).

Я не могу с уверенностью сказать, почему он жалуется на нераспределенные указатели, но у вас так много утечек и ошибок, выходящих за границы, когда пропущено так много кода, что трудно сказать наверняка Я ничего не пропустил, потому что код с ошибкой не для проверки. Вид ошибки, которую вы испытываете, может быть вызван повреждением кучи (которое вы определенно вызываете в разное время) или двойным delete[] указателем. Никакой очевидный код не делает этого, но вы не предоставили MCVE (то, что вы предоставили, не является ни минимальным, ни полным), поэтому оно может скрываться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...