【问题标题】:Why destructor doesn't free array memory?为什么析构函数不释放数组内存?
【发布时间】:2017-05-25 01:27:31
【问题描述】:

我的问题是为什么析构函数不释放临时数组的内存? Valgrind 告诉我,我在构造函数中使用了 new 运算符,但之后没有删除内存。当我简单地写delete temp 时,我在 Valgrind 中遇到了许多错误,例如 Invalid read of size、double free 等。你们能告诉我这里发生了什么吗?

array_xyz(const int r, const int c, double **arg_array) {

    rows = r;
    cols = c;
    array_xyz *temp = new array_xyz();
    temp->arr = new double *[rows];
    temp->rows = r;
    temp->cols = c;
    arr = new double *[rows];

    for (int i = 0; i < rows; i++) {
        arr[i] = new double [cols];
        temp->arr[i] = new double [cols];
    }

    for (int j = 0; j < rows; j++) {
        for (int k = 0; k < cols; k++)
            temp->arr[j][k] = arg_array[j][k];
    }

    arr = temp->arr;
    //delete temp; -> doesn't work, valgrind tells that I free memory twice
}

array_xyz() {
    rows = 0;
    cols = 0;
    arr = NULL;
}

~array_xyz() {
    for (int i = 0; i < rows; i++)
        delete []arr[i];
    delete []arr;
}

【问题讨论】:

  • 仅仅因为您要求您的 C++ 运行时释放内存,并不意味着它会立即释放到操作系统(页面中的其他分配可能也需要释放)。跨度>
  • 1) temp 在构造函数完成时不会被释放。 2) arr = temp-&gt;arr; 覆盖指向内存的指针,由arr = new double *[rows]; 分配,而不先释放它。 3) 为什么你还需要temp
  • arr 最终会在你正在构造的对象的析构函数中被删除,因此删除temp(其中有相同的地址)将使析构函数中的free 无效,并且所有之间的访问。

标签: c++ valgrind destructor delete-operator


【解决方案1】:

您同时分配arr(及其所有行)和temp_arr(及其所有行)。然后你做arr=temp_arr;。它不会将temp_arr 的值复制到arr。相反,它强制arr 指向与temp_arr 相同的地址。以前分配给arr 的整个内存现在是孤立的(没有指向它的指针,所以你不能释放它,它没有任何用处)。如果你删除temp_arr,它会自动删除arr,因为它们现在指向内存中的同一个地方。

【讨论】:

    【解决方案2】:

    这句话之后

    arr = temp->arr;
    

    arrtemp-&gt;arr 两个指针都指向相同的内存扩展。

    如果你添加这个satetment

    delete temp
    

    然后array_xyz 类的析构函数释放这个内存范围(以及动态分配数组的元素指向的范围)。同样,创建对象的析构函数也会删除相同的内存范围,因为它自己的指针arr 指向相同的内存。因此将尝试两次释放相同的内存范围。

    目前尚不清楚为什么要使用指针temp 指向的动态创建的中间对象。这完全是一个冗余代码,只会让构造函数的读者感到困惑。

    【讨论】:

      【解决方案3】:

      谢谢你,我明白了。我想将值从 arg_array 复制到 arr,好点那里甚至不需要 temp。

      解决办法:

        array_xyz(const int r, const int c, double **arg_array) {
      
          rows = r;
          cols = c;
          arr = new double *[rows];
      
          for (int i = 0; i < rows; i++) {
              arr[i] = new double [cols];
          }
      
          for (int j = 0; j < rows; j++) {
              for (int k = 0; k < cols; k++)
                  arr[j][k] = arg_array[j][k];
          }
      
      }
      

      【讨论】:

      • 顺便说一句,您可以在第二个循环中集成分配。无需重复两次。
      猜你喜欢
      • 2016-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-19
      • 1970-01-01
      • 1970-01-01
      • 2014-11-12
      • 1970-01-01
      相关资源
      最近更新 更多