【问题标题】:C++ double free error from function copy来自函数副本的 C++ 双重释放错误
【发布时间】:2016-01-22 18:22:16
【问题描述】:

我正在阅读 Stroustrup C++ 11 书籍,但遇到了双重免费异常。我知道它会释放内存两次,但我不明白为什么它会发生在通过副本传递的函数中:

#include <iostream>

using namespace std;

namespace ALL_Vector { 

  class Vector {
    public:
      // Intitialize elem and sz before the actual function
      Vector(int size) :elem {new double[size]}, sz {size} {};
      ~Vector() {delete[] elem;};

      double& operator[](int i) {
        return elem[i];
      };
      int size() {return sz;};
    private:
      double* elem;
      int sz;
  };


  void print_product(Vector& y) {
    double result {1};

    for (auto x = 0; x < y.size() ; x++){
      if (y[x] > 0) {result *= y[x]; };
    }

    cout << "The product of Vector y is: " << result << ", or so it would appear ;)\n";
  } 

}


/*
  Self test of the Vector class.  
*/

int main(){  
    ALL_Vector::Vector myVector(15);
    cout << "The size of Vector y is: " << myVector.size() << "\n"; 
    myVector[0] = 12;
    myVector[2] = 7;
    myVector[3] = 19;
    myVector[4] = 2;

    ALL_Vector::print_product(myVector);

  return 0;
}

print_product() 正在使用 Vector 类并创建一个包含重复内容的新 Vector?为什么这会导致双重免费?我假设在这种情况下 RIIA 以某种方式与 Vector::~Vector() 交互,类似于竞态条件?

我知道如果我更改它以通过引用传递它的参数,它将避免双重释放。我试图更好地理解通过副本传递的问题。

谢谢!

【问题讨论】:

  • 此代码正在运行fine
  • @LeFlou:它有一个测试没有发现的bug,即它违反了三规则。有趣的是,您的评论说代码工作正常,然后您的回答解释了为什么它不是 ^_^

标签: c++ double-free


【解决方案1】:

实际上,您调用 print_product 时引用了 myVector,所以一切都很好。
麻烦从按值传递 myVector 开始,因为默认的复制构造函数将复制 elem 指针而不是复制整个数组。
ALL_Vector::Vector elem 指针都指向相同的内存存储,因此会被删除两次。
为了解决这个问题,您必须实现复制构造函数来创建一个新数组并复制所有元素。

【讨论】:

  • 很好的解释,它解释了为什么通过引用传递会起作用。当我的新副本在函数调用结束时被销毁时,它会释放内存。所以我希望对原始对象的任何进一步引用都会核心转储,因为分配的内存已经被破坏了。
  • C++ 默认做浅拷贝。这意味着引用和指针被正确复制,但它们分别引用和指向的不是。动态分配对象的深拷贝必须手动编码。这将包括复制构造函数和复制赋值运算符。有时需要一个特殊的私有成员函数来分配和复制数据。
【解决方案2】:

如果您为每个值传递Vector,则会调用复制构造函数,而不是您已实现的构造函数。 在这种情况下,elem 不会被复制,而是指针被复制到新对象中,然后被析构函数删除两次。 您必须实现一个复制构造函数来分配一个新的elem 并复制所有元素。

【讨论】:

    猜你喜欢
    • 2014-11-10
    • 2017-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多