为什么我的堆已损坏?

时间:2010-09-27 14:42:55

标签: c++ corruption delete-operator

我收到错误 - 堆损坏,无法弄清楚原因。

我的基地:

h:

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 个答案:

答案 0 :(得分:7)

此代码存在明显问题:

  • 使用char * not std :: string需要手动内存管理
  • 使用 STL容器中的原始指针 过度复杂的清理代码
  • 使用CRT进行字符串操作 一个C ++'代码味道'

答案 1 :(得分:7)

您显示的代码没有明显错误,因此错误可能在您未显示的代码中。

对我来说,最直接可疑的是Base类拥有两个指针,并且没有定义复制构造函数或赋值运算符。这意味着如果您复制Base对象,最终将会有两个Base个对象指向相同的数据,当它们销毁时,它们会将其删除两次,从而导致堆损坏。

Army类也可能也有这个问题(因为它拥有几个Base指针),但你没有显示类的定义,所以它是否有一个不明显是否复制构造函数和赋值运算符。

最后,您尚未显示正在分配Base个对象的位置。是否有可能将它们传递到Army对象并删除Army对象之外的某个位置?或者Base*对象包含的Army可能是指堆栈中不应删除的对象?

答案 2 :(得分:5)

给出的代码没有错。 但是使用这种代码时,多次删除的可能性很高,我的意思是两次内存块deletin 会导致堆损坏。

答案 3 :(得分:3)

你没有发布有问题的部分代码,因为所有看起来都很正常。但是,它有很多常量问题:

Base(char* baseName, char* cityName);

字符串应作为const char*传递,除非它们被修改。

virtual ~Base();

不知道这是否需要virtual;无法看到它的子类是什么。

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

应该是const方法,因为它是const_iteratorlist<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();

答案 4 :(得分:1)

我没有看到任何问题。正如马特凯恩所说,它是如何填充的?

答案 5 :(得分:1)

堆损坏来自将更多数据复制到分配的堆单元中而不是分配给单元的内存。堆单元格的开头和结尾包含的数据比被覆盖的数据报告为堆损坏。

您尚未发布所有代码,我在您发布的代码中看不到问题,但我建议您使用像Valgrind这样的内存工具来帮助您诊断问题。