C ++删除指针数组 - 双重释放或损坏

时间:2013-05-16 12:13:10

标签: c++

这只是一个了解继承如何工作的测试项目。 Cat是Mammal的子类,它又是Animal的子类。

int main()
{
    Cat* cat1 = new Cat("nosy grey", 1.0d, 3);
    Cat* cat2 = new Cat("purply green", 2.0d, 4);

    Cat* cats[] = {cat1, cat2};

    delete [] cats;
 }

所以我真的不能那样做,因为那样我就明白了。

*** Error in `/home/max/git/info-2-ss/Blatt3/Aufgabe2/main.exe': double free or corruption (out): 0x00007fff55fd7b10 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x80a46)[0x7f3a07452a46]
/home/max/git/info-2-ss/Blatt3/Aufgabe2/main.exe[0x40178e]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0x7f3a073f3ea5]
/home/max/git/info-2-ss/Blatt3/Aufgabe2/main.exe[0x400d39]

当我的构造函数和析构函数被调用时输出,所以当我的Cats被创建时,我会得到这样的结果:

Called ctor of Animal with age: 3
Called ctor of Mammal with hairLength: 1
Called ctor of Cat with eyecolor: nosy grey

当我更改我的代码时,它会显示为:

delete [] *cats;

然后我会期望我的dtors会像每个猫一样被召唤:

Called dtor of Cat
Called dtor of Mammal 
Called dtor of Animal 

相反,我得到了这一行:

Called dtor of Cat

要点: 我怎样才能有效地删除我的数组,以便我的所有dtors都被调用?

4 个答案:

答案 0 :(得分:8)

这个

Cat* cats[] = {cat1, cat2};

使用自动存储创建指向猫的指针数组!您没有使用new[]分配数组,因此不应使用delete[]发布它。

答案 1 :(得分:2)

for(i = 0; i < len(cats)/sizeof(Cat); i++) {
  delete cats[i];
}
仅当您使用delete[] cats创建cats时,

cats = new Cat[num_cats]才有效。

答案 2 :(得分:2)

只有来自delete[]此数组,才应在数组上使用new ...[]!像这样:

Cat * cats = new Cat[2];
delete [] cats;

以上是正确的。但请注意,当然,在这种情况下,您无法将参数传递给构造函数。

现在,您的案例。您没有使用new创建数组,因此不应该删除数组本身(它在堆栈上,而不在堆中)。这就是delete[] cats崩溃的原因。 Next *cats将数组视为指针并取消引用它,即返回此指针指向的项。对于数组,它是数组的开头: *catscats[0] 相同。这就是为什么在第二次尝试中只删除第一个项目的原因。

最后,答案是:单独删除每个项目 ,而不是所有这些。对于你的简单案例:

delete cat1;
delete cat2;

或者,更一般地说:

for(int i = 0; i < sizeof(cats)/sizeof(cats[0]); ++i) {
    delete cats[i];
}

这里sizeof(cats)/sizeof(cats[0])是一个简单的技巧,通过将其大小除以元素的大小来获取数组中的项数。

通过此,您可以释放放置每个Cat个对象的内存。如果您担心指针数组所在的内存 - 它位于堆栈上,这意味着它将在从函数返回时自动释放。

答案 3 :(得分:0)

您不必删除数组本身,只需删除它的元素。您的数组cats位于堆栈中,因为您没有使用newmalloc创建数组。

所以你要做的就是

delete cat1;
delete cat2;

或等效

delete cats[0];
delete cats[1];