为什么这段代码不会导致内存泄漏?
int iterCount = 1000;
int sizeBig = 100000;
for (int i = 0; i < iterCount; i++)
{
std::auto_ptr<char> buffer(new char[sizeBig]);
}
操作系统:WinXP sp2,编译器:BCB.05.03
为什么这段代码不会导致内存泄漏?
int iterCount = 1000;
int sizeBig = 100000;
for (int i = 0; i < iterCount; i++)
{
std::auto_ptr<char> buffer(new char[sizeBig]);
}
操作系统:WinXP sp2,编译器:BCB.05.03
这是因为你(不)幸运。 auto_ptr
调用的是 delete
,而非 delete []
。这是未定义的行为。
尝试像下面这样做并看看你是否能如此幸运:
struct Foo
{
char *bar;
Foo(void) : bar(new char[100]) { }
~Foo(void) { delete [] bar; }
}
int iterCount = 1000;
int sizeBig = 100000;
for (int i = 0; i < iterCount; i++)
{
std::auto_ptr<Foo> buffer(new Foo[sizeBig]);
}
这里的想法是,Foo
的析构函数将不会被调用。
原因是这样的:当你使用 delete[] p
时,delete[]
的实现应该会遍历数组中的每个元素,调用它们的析构函数,然后释放指向 p 的内存。同样地,delete p
应该会先调用 p 的析构函数,然后释放内存。
char
类型没有析构函数,所以它仅会删除指向 p 的内存。在我上面的代码中,它不会析构数组中的每个元素(因为它没有调用 delete[]
),因此一些 Foo 可能会保留其本地 bar 变量而未被删除。
Foo
的析构函数实际上会被调用iterCount
次,但请注意是iterCount
* sizeBig
次。 - zarauto_ptr只在循环迭代期间存活,并在迭代完成时释放连接到它的对象。
编译器可以看到,在这种情况下,new[] 可以像 new一样分配空间,而无需存储元素的数量,因为不需要调用微不足道的char
析构函数。这就是为什么当 auto_ptr 的析构函数调用 delete 而非 delete[] 时,它不会引起问题,因为内存块实际上是按照 new 的方式分配的,而该分配可以与 delete 配对。
这是一个不应该做的事情的例子。编译器决定是否将 new[] 替换为 new。使用 delete 而不是 delete[] 或反之则是未定义的行为。
请参见为什么会有意地这样写?(有意不使用delete []来处理数组) 进行delete vs delete[]的讨论。