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

Die*_*mex 6 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;
 }
Run Code Online (Sandbox Code Playgroud)

所以我不能真的这样做,因为我得到了这个.

*** 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]
Run Code Online (Sandbox Code Playgroud)

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

Called ctor of Animal with age: 3
Called ctor of Mammal with hairLength: 1
Called ctor of Cat with eyecolor: nosy grey
Run Code Online (Sandbox Code Playgroud)

当我改变我的代码时,它会读取:

delete [] *cats;
Run Code Online (Sandbox Code Playgroud)

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

Called dtor of Cat
Called dtor of Mammal 
Called dtor of Animal 
Run Code Online (Sandbox Code Playgroud)

相反,我得到这一行:

Called dtor of Cat
Run Code Online (Sandbox Code Playgroud)

简介:如何有效地删除我的数组,以便我的所有dtors都被调用?

Sto*_*ica 8

这个

Cat* cats[] = {cat1, cat2};
Run Code Online (Sandbox Code Playgroud)

使用自动存储创建一个指向猫的指针数组!你没有分配数组new[],所以你不应该发布它delete[].


NIA*_*NIA 2

仅当您从 !获得此数组delete[]时,才应在数组上使用!像这样:new ...[]

\n\n
Cat * cats = new Cat[2];\ndelete [] cats;\n
Run Code Online (Sandbox Code Playgroud)\n\n

上面的说法应该是正确的。但请注意,当然,在这种情况下您不能将参数传递给构造函数。

\n\n

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

\n\n

最后,答案是:与其全部删除,不如单独删除每个项目。对于您的简单情况:

\n\n
delete cat1;\ndelete cat2;\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,更一般地说:

\n\n
for(int i = 0; i < sizeof(cats)/sizeof(cats[0]); ++i) {\n    delete cats[i];\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

这样您就可以释放每个对象所在的内存Cat。如果您担心指针数组所在的内存\ xe2\x80\x94 它位于堆栈上,这意味着它将在从函数返回时自动释放。

\n