C ++,复制构造函数混淆

时间:2013-03-06 21:52:58

标签: c++ gcc c++11 gcc-warning

说我创建了一个自定义Array类并有以下构造函数:

    Array::Array(size_t size)
    {
      mySize = size;
      //myData is of type int*
      myData = new int[mySize]; // this stuff is allocated on a heap
    }

据我所知,在这种情况下,默认的复制构造函数将实现如下:

    Array::Array(Array& a)
    {
      mySize = a.mySize;
      myData = a.myData; //points to the same memory on the heap
    }

最后,说我在main.cpp文件中有以下代码

     int main()
     {
       Array a(1);
       Array b(a); //copy constructor is invoked
     }

我期望的是由于删除了指向免费存储内存的myData指针而导致的内存泄漏,但是我遇到了运行时错误:

*** glibc detected *** ./main.out: double free or corruption (fasttop): 0x086ad008 ***

为什么?似乎~Disray()以某种方式自动释放堆上分配的内存 - 但这对我来说非常直观。也许我错过了什么?

更新:

      class Array{
         private:
           size_t mySize;
           int *myData;
           ...

更新2:

main.cpp中:

   #include <iostream>
   #include "array.h"

   int main()
   {
     Array a(1);
     Array b(a);
   }

array.h:

   #ifndef ARRAY_H_
   #define ARRAY_H_
   #include <stddef.h>
   class Array{
   private:
       size_t mySize;
       int *myData;
   public:
       Array(size_t size);
       ~Array();
       void set(int i,int val);
       int get(int i);
       size_t getSize();
   };
   #endif

array.cpp:

   #include "array.h"

   Array::Array(size_t size)
   {
     mySize = size;
     myData = new int[mySize];
   }

   Array::~Array()
   {
     delete[] myData;
   }

   void Array::set(int i, int val)
   {
     if(i>=0 && i<mySize)
       myData[i] = val;
   }

   int Array::get(int i)
   {
     if(i>=0 && i<mySize)
       return myData[i];
     else return -1;
   }
   size_t Array::getSize()
   {
     return mySize;
   }

5 个答案:

答案 0 :(得分:4)

我认为你的析构函数中有

 Array::~Array(void)
 {
      delete [] myData; //points to the same memory on the heap
 }

问题是双重免费

示例:

int main()
{
       Array a(1);  // here a.myData = 0x12345678
       Array b(a); //copy constructor is invoked // here b.myData = 0x12345678

       // pop  stack (call destroy of object)
       // delete b.myData
       // delete a.myData already delete
}

免费加载

修改 对于您的复制构造函数,请使用const,因为您没有修改。

 Array::Array(const Array& a)
 {
      mySize = a.mySize;
      myData = a.myData; //points to the same memory on the heap
 }

祝你好运!

答案 1 :(得分:3)

所以...尽管你声称,但事实证明你删除了析构函数中的数组,而复制构造函数是一个浅表副本,所以你得到一个双重删除。简单。

Array::~Array()
{
  delete[] myData;
}

由于这是一个动态数组,它应该拥有数据,因此你在析构函数中删除是正确的,但你需要在复制构造函数赋值运算符中进行“深度”复制。请参阅the rule of three

答案 2 :(得分:2)

您的副本是浅拷贝,因此 IF 您有一个释放内存的析构函数,每个对象都会尝试删除相同的内存。

你没有拥有来做一个浅拷贝。您可以编写自己的显式复制构造函数,将实际数据复制到新分配的数组中。

我喜欢Google对disable copy and assignment constructors的建议,而更喜欢明确的CopyFrom()方法。

答案 3 :(得分:1)

“double free”表示已将同一指针赋予delete[]两次。因为在你的析构函数中(大概)它是delete[] - 对象ab。实用的解决方案:使用std::vector,不要乱用原始数组等。

答案 4 :(得分:0)

我认为你的析构函数(来自数组'a'和'b')试图释放相同的内存(双重释放)。也许你应该在释放之前检查你的myData。