尝试处理嵌套对象/结构和动态数组时出现内存泄漏或内存错误。可能的 Xcode/malloc 问题



当我用Xcode编译并运行这个时,我得到错误,至少连续100次,malloc: *** error for object 0x100180: double free,调试器指向line C。奇怪的是,在我从中提取的代码中,发生了完全相同的错误,但调试器指向等同于line B的错误。我试过了,但无法复制。

如果我删除line A,代码可以工作,但是我得到一个主要的内存泄漏,在大约1分钟内使程序崩溃。删除line C可以解决问题,但不是一个有效的解决方案,因为a_class没有适当的析构函数。

#include <iostream>
#include <vector>
struct a_struct
{
    int* dynamic_array;
    a_struct(int length) {dynamic_array = new int [length];}
    a_struct() : dynamic_array(NULL) {}
    ~a_struct() { if (dynamic_array != NULL) {delete [] dynamic_array;} }  //Line A
};
class a_class
    {
    public:
        a_struct* the_structs;
        a_class() {Init();}
        a_class(a_class const & origin) {Init();}
        void Init(){
            the_structs = new a_struct [10];                              //Line B 
            for(int q=0; q<10; q++)
                the_structs[q] = a_struct(7);}
        ~a_class() { if (the_structs != NULL) {delete [] the_structs;} }  //Line C
    };
int main () 
{
    std::vector <a_class> the_objects;
    for(int q=0; q<10; q++)
        the_objects.push_back(a_class());
    while(1)
        for(int q=0; q <10; q++)
            for(int w=0; w <10; w++)
                the_objects[q].the_structs[w] = a_struct(7);
}

修复a_struct和a_class具有正确的复制构造函数和赋值操作符。如果还是有问题,再来找我。

确保你所有的课都遵循3的规则。我最近好像经常链接到那个页面。

问题是你试图做你自己的内存管理。

使用内置容器:

struct a_struct
{
    std::vector<int>    dynamic_array;
    a_struct(int length) : dynamic_array(length){}
    a_struct()           : dynamic_array() {}
};
class a_class
{
    public:
        std::vector<a_struct>   the_structs;
        a_class()                       {Init();}
        a_class(a_class const & origin) {Init();}
        void Init()
        {
            the_structs.resize(10); 
            for(int q=0; q<10; q++)
                the_structs[q] = a_struct(7);
        }
};

问题是a_struct没有正确的复制构造函数和operator =。由于这个原因,两个a_struct::dynamic_array同时指向相同的内存位置,并且都将在析构函数中调用delete[] dynamic_array;。因此,double delete

总是,记住当你在class中有一个行指针时,你应该做一个深度复制(你复制指针指向的内容),而不是一个浅复制(只是地址)。

在您的例子中,您可以这样更改定义:

struct a_struct
{
  int length_;  //<<--- add this for record
  int* dynamic_array;
  a_struct(int length) : length_(length) {dynamic_array = new int [length_]; }
  a_struct() : dynamic_array(NULL) {}
  a_struct(const a_struct &copy)  // <<--- copy ctor
  {
    do_copy(copy);
  }
  a_struct& operator = (const a_struct &copy)  // <<--- assignment operator
  {
    delete[] dynamic_array; // clear earlier array
    do_copy(copy);
    return *this;
  }
  ~a_struct() { if (dynamic_array != NULL) {delete [] dynamic_array;} }  //Line A
  void do_copy (const a_struct &copy)
  {
    // do necessary null checks for "copy"
    dynamic_array = new int[length_ = copy.length];
    memcpy(dynamic_array, copy.dynamic_array, length_);
  }
};

与其他class相同的预防措施

问题是a_struct中隐式生成的复制构造函数不进行深度复制,但析构函数总是假设为每个实例分配了内存。您需要为它创建一个执行深度复制的复制构造函数。但更好的是只使用std::vector而不是new和delete。这样,您就不必担心要记住保持所有构造函数的正确性。

另外,a_class的复制构造函数实际上并不复制对象。当它不支持预期的复制语义时,这几乎肯定会给您带来问题。

相关内容

  • 没有找到相关文章

最新更新