3

我收到一个错误 - 堆损坏,不知道为什么。

我的基地:

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;

};  

cp:

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();
 }  

我究竟做错了什么?

4

6 回答 6

7

此代码的可见问题:

  • 使用 char* 而不是 std::string 需要手动内存管理
  • 在 STL 容器中使用原始指针会使清理代码过于复杂
  • 使用 CRT 进行字符串操作是 C++ 的“代码味道”
于 2010-09-27T14:50:13.373 回答
7

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

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

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

最后,您还没有显示Base分配对象的位置。它们是否有可能被传递到一个Army对象中并在Army对象之外的某个地方被删除?或者对象所Base*包含的可能Army是指堆栈上不应该删除的对象?

于 2010-09-27T14:50:41.533 回答
5

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

于 2010-09-27T15:28:14.503 回答
3

您没有发布有问题的代码部分,因为所有这些看起来都很正常。但是,它有很多 const 正确性问题:

Base(char* baseName, char* cityName);

字符串应该传递 asconst 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();.

于 2010-09-27T14:54:13.433 回答
1

我看不出有什么问题。正如马特凯恩所说,它是如何被填充的?

于 2010-09-27T14:46:47.637 回答
1

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

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

于 2010-09-27T14:50:02.797 回答