从堆和内存泄漏中删除 C++ 数组
deleting c++ array from heap and memory leak
我有一个关于从堆内存中删除数组的问题。在一本书和 this blog and in other resources such as this one 上,我读到要从堆中删除数组,我们必须在 delete
关键字之后使用 []
,这样如果我们不使用 []
我们将有内存泄漏。
例如,考虑下面的代码。
//constructing array
int *s = new int[10];
// deleting array from heap
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
无法检测到这种内存泄漏,是否有其他包可以检测到这种情况?
在不使用 []
的情况下对数组调用 delete
会导致未定义的行为。未定义的行为可能是数组被正确删除,这似乎是您观察到的。但是,您不能依赖它。
Martin Broadhurst 已经给出了正确的 。我将给出技术细节答案:
在 delete
上使用 delete[]
的要点是,delete
运算符无法知道传递的指针是指向数组还是指向单个对象.因此,delete
只删除一个对象,而 delete[]
调用一些额外的魔法来恢复数组的大小,并继续删除所有元素。
现在删除由两个不同的部分组成:
对象必须通过调用析构函数来销毁。对于数组,这意味着对每个数组元素调用一次析构函数。
已使用的内存必须标记为可用,以便可以重复使用。这是 C++ 中全局 operator delete()
的工作。由于数组是连续存储的,因此这是对整个数组的一次调用。
valgrind
只关心内存。因此,它挂钩内存分配函数,如 malloc()
、free()
、operator new()
和 operator delete()
.
当你调用 delete
而不是 delete[]
时会发生什么,第一个对象被破坏,指针被传递给 operator delete()
。 operator delete()
不知道存储在内存区域中的对象,它们已经被销毁了,所以它会成功地将内存区域标记为空闲。 valgrind
看到这个 operator delete()
调用,并且很高兴,因为所有内存都可以免费重用。但是,您的代码未能正确销毁除第一个数组元素之外的所有元素。这很糟糕。
我有一个关于从堆内存中删除数组的问题。在一本书和 this blog and in other resources such as this one 上,我读到要从堆中删除数组,我们必须在 delete
关键字之后使用 []
,这样如果我们不使用 []
我们将有内存泄漏。
例如,考虑下面的代码。
//constructing array
int *s = new int[10];
// deleting array from heap
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
无法检测到这种内存泄漏,是否有其他包可以检测到这种情况?
在不使用 []
的情况下对数组调用 delete
会导致未定义的行为。未定义的行为可能是数组被正确删除,这似乎是您观察到的。但是,您不能依赖它。
Martin Broadhurst 已经给出了正确的
在 delete
上使用 delete[]
的要点是,delete
运算符无法知道传递的指针是指向数组还是指向单个对象.因此,delete
只删除一个对象,而 delete[]
调用一些额外的魔法来恢复数组的大小,并继续删除所有元素。
现在删除由两个不同的部分组成:
对象必须通过调用析构函数来销毁。对于数组,这意味着对每个数组元素调用一次析构函数。
已使用的内存必须标记为可用,以便可以重复使用。这是 C++ 中全局
operator delete()
的工作。由于数组是连续存储的,因此这是对整个数组的一次调用。
valgrind
只关心内存。因此,它挂钩内存分配函数,如 malloc()
、free()
、operator new()
和 operator delete()
.
当你调用 delete
而不是 delete[]
时会发生什么,第一个对象被破坏,指针被传递给 operator delete()
。 operator delete()
不知道存储在内存区域中的对象,它们已经被销毁了,所以它会成功地将内存区域标记为空闲。 valgrind
看到这个 operator delete()
调用,并且很高兴,因为所有内存都可以免费重用。但是,您的代码未能正确销毁除第一个数组元素之外的所有元素。这很糟糕。