我正在尝试理解delete []的使用。以下代码是否会发生内存泄漏?
int * getArray( )
{
int *r = new int[10];
for (int i = 0; i < 10; ++i)
r[i] = i;
return r;
}
int main ()
{
int *array;
for ( int i = 0; i < 10; i++ ) // main loop
array = getArray();
return 0;
}
主循环似乎是为10个数组分配内存,其中只有最后一个数组有一个有效的指针。如果这是内存泄漏,我如何释放存储前9个阵列的内存?
我也可以使用const int r[10];
代替int *r = new int[10];
进行编译。可以使用const
来避免内存泄漏吗?
答案 0 :(得分:6)
对new
的每次通话都必须与对delete
的通话配对,以避免内存泄漏(或new[]
和delete[]
)。
如何删除内存取决于您正在做什么,但由于您不能在for-loop之外保持访问权限,因此您可以轻松地将其删除。 for循环。
for (int i = 0; i < 10; ++i)
{
array = getArray();
/* do something with 'array' */
delete[] array;
}
更好的是,为什么不使用std::vector<int>
并避免直接执行任何内存分配?
修改强>
正如@Niall在评论中提到的那样,您还应该熟悉std::unique_ptr
(假设您的编译器支持它)。它使用RAII(Wikipedia link,cppreference link)来自动处理内存管理。例如,std::unique_ptr<int[]>
会在课程超出范围时自动调用delete[]
。
答案 1 :(得分:3)
delete
(或new
和new[]
)拨打delete[]
,就会发生内存泄漏。 for ( int i = 0; i < 10; i++ ) // main loop
array = getArray();
如你所说,将创建无法恢复(前9个阵列)地址的内存。无法获取地址,以便您可以正确处理此内存。你需要做这样的事情:
int *array[10]
...
for ( int i = 0; i < 10; i++ ) // main loop
array[i] = getArray();
以便您可以正确删除所有数组:
for ( int i = 0; i < 10; i++ )
delete[] array[i];
答案 2 :(得分:1)
正如其他答案所解释的那样,您有一个memory leak(使用const
对他们没有帮助。)
有几个系统(特别是Linux)将valgrind移植到它们。如果可能的话使用它(在运行时测试)。因此,使用g++ -std=c++11 -Wall -Wextra -g
将您的C ++ 11代码编译为./myprog
可执行文件,然后运行valgrind ./myprog
;它将在运行时为您提供有用的诊断。
使用最近的GCC,您还可以将-fsanitize=address
传递给编译器。详细了解address sanitizer。
顺便说一句,你应该经常在你的C ++代码中使用smart pointers,例如std::shared_ptr或std::unique_ptr。另请阅读RAII,weak references和rule of five。
您可能还会了解有关garbage collection技术的更多信息(reference counting是一个非常有限的技术,对cyclic图表不友好,但对DAG s来说已经足够了。您可以考虑使用Boehm's conservative garbage collector。另请参阅this。
答案 3 :(得分:1)
1 - 你确实有内存泄漏。要解决这个问题,您可以在完成每个阵列后明确删除。
for ( int i = 0; i < 10; i++ ) {
int *array = getArray();
// ... Do stuff ...
delete[];
}
或者为数组返回unique_ptr
。这样你就不必删除任何内容。
std::unique_ptr< int[] > getArray( )
{
std::unique_ptr< int[] > r{ new int[10] };
for (int i = 0; i < 10; ++i) {
r[i] = i;
}
return std::move( r );
}
在这两种情况下,您都无法猜测数组的大小。你只知道你得到了10个元素的数组。
您可以使用std::array
为您管理内存并保持数组长度可见。
2 - 如果您使用static
,您将始终返回相同的数组,并且无需删除。