std :: auto_ptr,删除[]和泄漏

时间:2009-07-29 07:32:48

标签: c++ memory-leaks auto-ptr

为什么此代码导致内存泄漏?

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

2 个答案:

答案 0 :(得分:15)

因为你(非)幸运。 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将使其本地条形变量不被删除。

答案 1 :(得分:3)

auto_ptr只会在循环迭代期间存活,并会在迭代完成时释放连接到它的对象。

编译器可以看到,在这种情况下, new [] 可以以与 new 相同的方式分配空间 - 而无需在任何地方存储元素数量,因为不需要调用琐碎的char析构函数 - 这就是为什么以后当auto_ptr的析构函数而不是 delete [] 调用 delete 时它会导致没有问题,因为内存块实际上已经存在已经以 new 的方式分配,并且该分配可以与 delete 配对。

这是一个不做的事情的例子。由编译器决定是否用 new 替换 new [] 。使用 delete 而不是 delete [] ,反之亦然是未定义的行为。

有关删除删除[] 的讨论,请参阅Why would you write something like this? (intentionally not using delete [] on an array)