是删除p其中p是指向数组的指针始终是内存泄漏吗?

时间:2010-03-09 09:01:52

标签: c++ memory-management

在软件会议中讨论之后,我已经着手查明是否删除带有普通delete的动态分配的原语数组会导致内存泄漏。

我编写了这个小程序并使用在Windows XP上运行的visual studio 2008进行编译:

#include "stdafx.h"
#include "Windows.h"

const unsigned long BLOCK_SIZE = 1024*100000;
int _tmain()
{
    for (unsigned int i =0; i < 1024*1000; i++)
    {
        int* p = new  int[1024*100000];
        for (int j =0;j<BLOCK_SIZE;j++) p[j]= j % 2;
        Sleep(1000);
        delete p;
    }
}

我比使用任务管理器监视我的应用程序的内存消耗,令人惊讶的是内存已正确分配和释放,分配的内存没有像预期的那样稳定增加

我已修改我的测试程序以分配非原始类型数组:

#include "stdafx.h"
#include "Windows.h"


struct aStruct
{
    aStruct() : i(1), j(0) {}

    int i;
    char j;
} NonePrimitive;

const unsigned long BLOCK_SIZE = 1024*100000;
int _tmain()
{
    for (unsigned int i =0; i < 1024*100000; i++)
    {
        aStruct* p = new  aStruct[1024*100000];
        Sleep(1000);
        delete p;

    }
}

运行10分钟后,内存无意义增加

我编制了警告级别为4的项目并没有收到任何警告。

可视化工作室运行时是否可以跟踪分配的对象类型,以便在该环境中deletedelete[]之间没有区别?

8 个答案:

答案 0 :(得分:19)

delete p,其中p是一个数组,称为未定义行为。

具体来说,当你分配一个原始数据类型数组(int)时,编译器没有很多工作要做,所以它把它变成一个简单的malloc(),所以delete p可能会起作用。

删除p通常会在以下情况下失败:

  • p是一个复杂的数据类型 - 删除p;我不知道打电话给个人的破坏者。
  • “user”重载operator new []并删除[]以使用不同的堆到常规堆。
  • 调试运行时重载operator new []和delete []以添加数组的额外跟踪信息。
  • 编译器决定需要存储额外的RTTI信息以及删除p的对象;不明白,但删​​除[] p;会。

答案 1 :(得分:17)

不,这是未定义的行为。不要这样做 - 使用delete[]

在VC ++ 7到9中,它恰好工作when the type in question has trivial destructor,但它可能会停止在更新版本上运行 - 通常具有未定义行为的东西。不管怎么说都不要这样做。

答案 2 :(得分:3)

它被称为未定义的行为;它可能有用,但你不知道为什么,所以你不应该坚持下去。

我不认为Visual Studio会跟踪您如何分配对象(如数组或普通对象),并神奇地将[]添加到您的删除中。它可能会将delete p;编译为与您使用p = new int分配的相同代码,并且正如我所说,由于某种原因它可以正常工作。 但你不知道为什么。

答案 3 :(得分:3)

答案是肯定的,它会导致内存泄漏,因为它不会为数组中的每个项调用析构函数。这意味着数组中项目拥有的任何额外内存都将泄漏。

更符合标准的答案是它是未定义的行为。例如,编译器完全有权对阵列使用不同的内存池而不是非阵列项。以新方式执行但删除另一方可能会导致堆损坏。

您的编译器可能会保证标准不会,但第一个问题仍然存在。对于没有额外内存的POD项目(或文件句柄等资源),您可能没问题。

即使它对您的编译器和数据项是安全的,也不要这样做 - 它也会误导任何试图阅读您的代码的人。

答案 4 :(得分:2)

不,在处理数组时应该使用delete[]

答案 5 :(得分:2)

仅使用delete将不会调用数组中对象的析构函数。虽然它可能按预期工作但未定义,因为它们的确切工作方式存在一些差异。所以你不应该使用它,even for built in types

答案 6 :(得分:1)

原因似乎不是泄漏内存是因为删除通常基于free,已经知道需要释放多少内存。但是,c ++部分不太可能正确清理。我打赌只会调用第一个对象的析构函数。

答案 7 :(得分:1)

使用delete with []告诉编译器在数组的每个项目上调用析构函数。 如果在使用动态内存分配的对象数组上使用,则不使用delete []会导致内存泄漏,如下所示:

class AClass
{
public:
    AClass()
    {
        aString = new char[100];
    }
    ~AClass()
    {
        delete [] aString;
    }
private:
    const char *aString;
};

int main()
{
    AClass * p = new  AClass[1000];
    delete p; // wrong
    return 0;
}