C++复制构造函数上的双重释放错误

Double free error on a C++ copy constructor

本文关键字:释放 错误 复制 构造函数 C++      更新时间:2023-10-16

我在这个代码上有一个双重释放或损坏(快速)错误。 我想我错过了"复制构造函数"上的一些东西。

class Vector{
int taille;
int* ptr;
public:
Vector():taille(0), ptr(NULL){
...
}
Vector(int n){
...
}
//The most important one
Vector(const Vector& source){
if(source.ptr != NULL){
taille = source.taille;
ptr = new int[taille];
for(int i=0;i<taille;i++) ptr[i]=source.ptr[i];
}else{
taille=0;
ptr=NULL;
}
cout << "Copy constructor" << endl;
}
~Vector(){
if(ptr!=NULL) delete ptr;
}
};

这是测试:

int main()
{
Vector b(5);
Vector a(b);
a=Vector(12);
return 0;
}

上面的 = 运算符不调用复制构造函数。为什么?

它说:"双重自由或腐败(快速)">

使用表达式

a = Vector(12)

一些事情正在发生:

  1. 首先创建一个新的临时Vector对象(从Vector(12))。这是使用Vector(int)构造函数构造的。

  2. 临时对象被指派a,使用a.operator=(<temporary object>)

    默认编译器生成的operator=函数执行简单的成员分配,即它基本上执行ptr = other.ptr。这意味着您现在有两个对象ptr成员指向同一内存:临时对象和a

  3. 一旦进行分配,临时对象就会被销毁。这意味着该对象占用的内存被传递给delete(实际上应该delete[])。

    这当然意味着a.ptr不再指向有效内存,当它稍后超出范围并被破坏时,您尝试delete已删除的内存。

这里没有进行复制构建。这都是复制分配。复制构造仅用于实际构造,当创建对象(临时或非临时)时。我想你很困惑,因为=符号可用于复制构造,如

Vector a = b;  // This is a copy-construction
// The copy-constructor of `a` is called with
// a reference to `b` as argument
// It's equal to `Vector a(b)`

这与分配非常不同

a = b;  // This is a plain assignment
// It is equal to `a.operator=(b)`

崩溃是通过遵循三、五或零规则之一来解决的。

我还建议您阅读例如此规范赋值运算符参考。

您正在分配a = Vector(12)中创建临时Vector,该通过operator=分配给a。临时Vector在赋值语句结束时销毁,a在函数结束时销毁。两者都指向同一个分配的数组,因为您没有定义复制分配operator=

http://www.cplusplus.com/doc/tutorial/operators/