指针内存泄漏的C ++数组

时间:2011-11-03 19:34:36

标签: c++ memory-leaks valgrind

在我的班级中,我有一个动态分配的指针数组。我的声明:

 array = new Elem* [size];
 for (int i = 0; i < size; i++) {
    array[i] = NULL;
 }

所以有一个指针数组,其中每个指针指向一个简单的Elem结构。

主要问题是,我应该如何正确地释放数组。如果我只使用:

for (int i = 0; i < size; i++) {
   delete array[i];
}

Valgrind报告1个未释放的块,它被追踪到'array = new Elem * [size];'的行状态。

另一方面,如果我添加到上一个代码:

delete array;

我认为这是正确的,valgrind报告了0个未释放的块,这是完美的,但它报告

Mismatched free() / delete / delete []

正好在'删除数组;'的行上是。我也试过'删除[]数组',但那只是“1个未释放的块”!如果有人能够以正确的方式向我解释,我将不胜感激。

修改 所以使用:

for (int i = 0; i < size; i++) {
   delete array[i];
}
delete[] array;

工作得很好。它在我的一个班级(我有两个类似的)工作,另一个仍然报告一些小漏洞。我认为这只是一个小错误,但是valgrind仍指向

array = new Elem* [size];

表示。

EDIT2: 我也解决了这个问题,谢谢你的贡献!

4 个答案:

答案 0 :(得分:8)

你需要:

delete [] array;

因为它是一个数组。

我刚刚注意到你的注意事项,你也试过了 - 这是正确的做法,我不知道你为什么还会收到错误。

修改:这需要更详尽的解释。

使用new创建指针时,指针可能是单个元素或元素数组,具体取决于您使用的语法。但两种情况下指针类型都相同!编译器依赖于您知道指针指向的内容并相应地对其进行处理。

Elem ** single = new Elem*;    // pointer to one pointer
single[0] = new Elem;          // OK
single[1] = new Elem;          // runtime error, but not compile time

Elem ** array = new Elem* [2]; // pointer to array of pointers
array[0] = new Elem;           // OK
array[1] = new Elem;           // OK

删除指针时,将为其指向的对象或数组的每个元素调用析构函数。但由于指针类型在每种情况下都是相同的,编译器依赖于您为其提供正确的语法,因此它知道该怎么做。

delete single;
delete [] array;

在您的情况下,数组的元素也是指针,指针没有析构函数。这意味着这些指针不会被删除,如果你不先删除它们将成为内存泄漏。在最终删除之前,有一个循环可以单独删除它们。

答案 1 :(得分:7)

你应该释放数组中的所有内容(如果是动态分配的),然后释放数组本身。

for (int i = 0; i < size; i++) { // only free inside if dynamically allocated - not if just storing pointers
   delete array[i];
}
delete[] array; // necesarry

答案 2 :(得分:5)

删除数组的语法如下:

delete[] array;

你的for循环删除数组元素指向的对象很好。删除数组本身是唯一的问题。您需要 for循环,然后delete[]才能处理数组本身。

for (int i = 0; i < size; i++) {
   delete array[i];
}
delete[] array;

我怀疑您已尝试使用for循环或delete[],但不是两者都在一起。如果你这样做仍然有泄漏或错误,那么你需要向我们展示分配作为数组元素的指针的代码。


使用std::vector<>代替数组意味着您可以不再担心这些细节,并转向更高级别的抽象。

答案 3 :(得分:2)

在这种情况下,您需要 both

for (int i = 0; i < size; i++) {
   delete array[i];
}
delete[] array;

每次拨打delete时,您都会拨打new一次。

请注意,虽然您需要在此处致电delete[] array(因为您使用new[]分配了它),但delete[]运算符会调用析构函数数组元素指向的对象。这是因为delete[]运算符调用数组中对象上的析构函数,并且数组包含指针但不包含对象。指针本身不具有析构函数。