检测到堆腐败 - 带指针的类

时间:2015-05-11 18:51:47

标签: c++ constructor heap-corruption

以下代码会导致断言错误。此外,警告错误消息表示检测到堆损坏。

class A {
    int* a; // dynamic array of ints
    A() {};
    A(int size) {
        a = new int[size]; 
    }
    ~A() {
        delete [] a;
        a = nullptr;
    }
}

*** in code somewhere ***
int size = 5;
A temp = A(size);

2 个答案:

答案 0 :(得分:5)

错误的原因是:
温度= A(大小);
这一行称为:

  1. A&#39> 复制构造函数,此处:temp = A(size); 问题是,这会创建一个浅层副本,因为它使用默认的复制构造函数,并且我们在类中有一个指针,需要深层复制!
  2. A&#39> 参数化构造函数,此处: A(大小);
  3. A 析构函数,它将删除由 A temp 创建的指针并将其置空。
  4. temp 变量超出范围时,其析构函数将再次被称为 ,从而导致断言失败。

      

    <强>解决方案:

      的 1。临时(大小);
      而不是A temp = A(size);

      这只会调用参数化构造函数。   

      的 2。覆盖默认的复制构造函数以创建深层副本!

      

    Marco Costa 的另一项修正   最好在默认构造函数中将 a 初始化为nullptr。

         

    user4581301的另一项更正
      如果 a 是nullptr,析构函数应该在删除之前检查。

      

    其他读物:   
    1。 Why aren't pointers initialized with NULL by default?   
    2。 Chad 建议的Rule-of-Three becomes Rule-of-Five with C++11?   
    3。 Chad

    建议scalar deleting destructor issue

答案 1 :(得分:1)

正如其他人所说,你需要遵循3(或5)的规则。

但是,您的课程还有另一个问题,那就是您没有记录元素的数量。如果要正确实现这些功能,这一点至关重要。没有标准方法可以检索用于调用new[]的项目数,因此您需要将此大小值记录为成员。

class A {
    int* a; 
    int aSize;  // records the number of elements.
    A() : aSize(0), a(nullptr) {}
    A(int size) : aSize(size) 
    { a = new int[size]; }

//...
};

您需要将size成员添加到您的类中,否则您无法实现所需的复制功能。