Почему моя куча повреждена? - PullRequest
3 голосов
/ 27 сентября 2010

Я получаю ошибку - повреждение кучи, не могу понять, почему.

Моя база:

ч:

class Base
{
public :
    Base(char* baseName, char* cityName);
    virtual ~Base();

    list<Vehicle*>::const_iterator GetEndList();
    void PrintAllVehicles(ofstream &ResultFile) const;
    char* GetBaseName() const;
    char* GetLocation() const;
    void InsertNewVehicleToBase(Vehicle* newVehicle);
    list<Vehicle*>::const_iterator FindVehicle(char* id);
    void RemoveVehicle (list<Vehicle*>::const_iterator beg);



 private:
    char* m_name;
    char* m_location;
    list<Vehicle*> m_baseVehicles;

};  

cpp:

Base::Base(char* baseName, char* cityName)
{
    m_name = new char [strlen(baseName)+1];
    strcpy(m_name, baseName);
    m_location = new char [strlen(cityName)+1];
    strcpy(m_location, cityName);
}

Base::~Base()
{
    delete [] m_name;
    delete [] m_location;
    //m_baseVehicles.clear();
}

деструктор армии:

Army::~Army()
{
    list<Base*>::iterator baseIter = m_basesList.begin();
    for (baseIter ; baseIter != m_basesList.end() ; ++baseIter)
        delete (*baseIter);
    m_basesList.clear();
 }  

Чтоя делаю не так?

Ответы [ 6 ]

7 голосов
/ 27 сентября 2010

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

Самым подозрительным моментом для меня является то, что класс Base владеет двумя указателями и не имеет определенного конструктора копирования или оператора присваивания. Это означает, что если вы когда-нибудь скопируете объект Base, у вас получится два объекта Base, указывающие на одни и те же данные, и, когда они будут уничтожены, они удалят их дважды, вызывая повреждение кучи.

Класс Army также может иметь эту проблему (так как ему принадлежит несколько Base указателей), но вы не показываете определение класса, поэтому не очевидно, имеет ли он конструктор копирования и присваивание оператор или нет.

Наконец, вы не показали, где располагаются объекты Base. Возможно ли, что они передаются в объект Army, а также удаляются где-то за пределами объекта Army? Или, возможно, Base*, содержащийся в объекте Army, ссылается на объекты в стеке, которые не следует удалять?

7 голосов
/ 27 сентября 2010

Видимые проблемы с этим кодом:

  • использование char * not std :: string требует ручного управления памятью
  • Использование необработанных указателей в контейнерах STL усложняет код очистки
  • использование CRT для манипулирования строками - это C ++ 'запах кода'
5 голосов
/ 27 сентября 2010

Ничего плохого в приведенном фрагменте кода. Но с этим типом кода существует высокая вероятность многократного удаления , я имею в виду удаление блока памяти дважды , что приводит к повреждению кучи.

3 голосов
/ 27 сентября 2010

Вы не опубликовали ту часть кода, в которой возникла проблема, потому что все это выглядит довольно нормально. Тем не менее, у него много проблем с правильностью:

Base(char* baseName, char* cityName);

Строки должны передаваться как const char*, если они не изменяются.

virtual ~Base();

Не знаю, должно ли это быть virtual; не могу видеть, каковы его подклассы.

list<Vehicle*>::const_iterator GetEndList();

Должен быть методом const, так как это const_iterator: list<Vehicle*>::const_iterator GetEndList() const;

char* GetBaseName() const;
char* GetLocation() const;

Они должны возвращать const char*, поскольку ваш код не настроен для обработки изменяемого имени и местоположения.

list<Vehicle*>::const_iterator FindVehicle(char* id);

Опять же, должен быть метод const: list<Vehicle*>::const_iterator FindVehicle(char* id) const;

Base::~Base()
{
    delete [] m_name;
    delete [] m_location;
    //m_baseVehicles.clear();
}

Вам не нужно m_baseVehicles.clear();, потому что это происходит в любом случае сразу после деструктора. Тем не менее, вам нужно удалить автомобили, если на них нет ссылок, иначе вы получите утечку.

армейский дистрактор:

"деструктор". А где остальные Army?

Army::~Army()
{
    list<Base*>::iterator baseIter = m_basesList.begin();
    for (baseIter ; baseIter != m_basesList.end() ; ++baseIter)
        delete (*baseIter);
    m_basesList.clear();
 }  

Опять же, вам не нужно m_basesList.clear();.

1 голос
/ 27 сентября 2010

Повреждения кучи происходят из-за копирования большего количества данных в выделенную ячейку кучи, чем в памяти, выделенной для ячейки. В начале и конце ячеек кучи содержатся данные, которые после перезаписи будут считаться повреждением кучи.

Вы не опубликовали весь код, и я не вижу проблемы в опубликованном вами коде, но я бы посоветовал использовать инструмент памяти, такой как Valgrind, чтобы помочь вам диагностировать проблему.

1 голос
/ 27 сентября 2010

Я не вижу никаких проблем.Как сказал Мэтт Кейн, как оно заполняется?

...