我的问题是从堆内存中删除数组。我读了一本书和this blog以及其他资源like this one,并且所有人都说如果要从堆中删除数组,我们必须在[]
函数之后使用delete
,所以如果我们在不使用[]
的情况下编写代码,然后我们泄露了内存。
int *s = new int[10];
delete [] s;
我在Linux中使用valgrind
软件包测试了这个小程序(这个软件包可以检查错误编码产生的泄漏内存量)。通过Linux下面的命令,我们看到一切都没问题
sudo valgrind --leak-check=full ./<path_to_exe_file>
这是Linux命令的输出
==4565== HEAP SUMMARY:
==4565== in use at exit: 0 bytes in 0 blocks
==4565== total heap usage: 1 allocs, 1 frees, 40 bytes allocated
==4565==
==4565== All heap blocks were freed -- no leaks are possible
但是当我尝试使用delete
而不使用[]
时出现了我的问题,当我检查valgrind
的输出时,我看到所有堆内存都被释放,所以它是否正确?或valgrind
不知道整个堆没有被释放,阵列的某些部分仍然在那里!! ??如果valgrind
无法检测到这种泄露的内存,那么是否有任何可以检测到它的包。
答案 0 :(得分:5)
在不使用delete
的情况下在数组上调用[]
会导致未定义的行为。未定义的行为可能是正确删除了数组,这似乎是您观察到的。但是,你不能依赖它。
答案 1 :(得分:2)
Martin Broadhurst已经给出了正确的language-lawyer answer。我将提供技术细节答案:
使用delete[]
超过delete
的要点是,delete
运算符无法知道传递的指针是指向数组还是指向单个对象。因此,delete
仅删除单个对象,而delete[]
调用一些额外的魔法来恢复数组的大小,并继续删除所有元素。
现在删除包含两个不同的部分:
必须通过调用析构函数来销毁对象。对于数组,这意味着每个数组元素都有一个析构函数调用。
使用的内存必须标记为空闲,以便可以重复使用。这是C ++中全局operator delete()
的工作。由于数组是连续存储的,因此这是对整个数组的单个调用。
valgrind
只关心记忆。因此,它挂钩内存分配函数,如malloc()
,free()
,operator new()
和operator delete()
。
当您调用delete
而不是delete[]
时会发生什么,第一个对象被破坏,指针被传递到operator delete()
。 operator delete()
不知道存储在内存区域内的对象,它们无论如何都已被销毁,因此它会成功将内存区域标记为空闲。 valgrind
看到此operator delete()
电话,并且很高兴,因为所有内存都可以重复使用。但是,您的代码无法正确地破坏除第一个数组元素之外的所有数组元素。这很糟糕。