为什么这段代码不会导致内存泄漏?

时间:2013-09-27 07:11:53

标签: c++ memory-leaks valgrind

我使用valgrind--leak-check=full检查了C ++中的以下代码,并且没有内存泄漏。那是为什么?

char *p = new char[256];
delete p;
据我所知,

new[]应与delete[]匹配。

6 个答案:

答案 0 :(得分:38)

尽管@KillianDS说它是未定义的行为,但差异可能与deletedelete[]释放底层内存的事实有关。 delete[]的要点是在释放内存之前调用数组中每个对象的析构函数。由于charPOD并且没有析构函数,因此在这种情况下两者之间没有任何有效差异。

然而,你绝对不应该依赖它。

答案 1 :(得分:12)

仅当delete指向基本数据类型(例如char或int)时,

delete[]p才相等。

如果p指向对象数组,则结果将不同。请尝试以下代码:

class T {
public:
    T() { cout << "constructor" << endl; }
    ~T() { cout << "destructor" << endl; }
};

int main()
{
    const int NUM = 3;
    T* p1 = new T[NUM];

    cout << p1 << endl;
    //  delete[] p1;
    delete p1;

    T* p2 = new T[NUM];
    cout << p2 << endl;
    delete[] p2;
}

通过使用delete[],将调用数组中T的所有析构函数。使用delete只会调用p[0]的析构函数。

答案 2 :(得分:11)

当我尝试这个时,valgrind报告:

==22707== Mismatched free() / delete / delete []
==22707==    at 0x4C2B59C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22707==    by 0x40066D: main (in /home/andrew/stackoverflow/memtest)
==22707==  Address 0x5a1a040 is 0 bytes inside a block of size 256 alloc'd
==22707==    at 0x4C2C037: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22707==    by 0x40065D: main (in /home/andrew/stackoverflow/memtest)

这不是真正的内存泄漏,但是valgrind确实注意到了这个问题。

答案 3 :(得分:7)

因为它是未定义的行为。在您的情况下,delete可能会在您的编译器中执行delete []的工作,但它可能无法在另一台计算机上运行。

答案 4 :(得分:1)

这是undefined behavior,因此我们无法推断其行为。如果我们查看草案C ++标准部分3.7.4.2 释放函数,段落 3 表示(强调我的):

  

[...]否则,如果标准库中提供给operator delete(void *)的值不是先前调用new operator(std:)返回的值之一,则行为是未定义的。 :size_t)或运算符new(std :: size_t,conststd :: nothrow_t&amp;)在标准库中,如果在标准库中提供给operator delete [](void *)的值是,则行为未定义上次调用运算符new [](std :: size_t)或operator new [](std :: size_t,const std :: nothrow_t&amp;)返回的值中没有一个值   标准库。

实际细节将是implementation-defined behavior,可能会有很大差异。

答案 5 :(得分:0)

deletedelete []之间的区别在于编译器添加了代码来调用删除对象的析构函数。说这样的话:

    class A
    {
        int a;
        public:
            ...
            ~A() { cout<<"D'tor"; }
    };

    a=new A[23];
    delete [] a; 

delete [] a;转换为类似

的内容
   for (int i=0; i<23; i++)
   {
       a[i].A::~A();
   }
   std::delete a;

因此,对于您的情况,因为它是内置数据类型,所以没有析构函数可以调用。所以,它转变为,

   std::delete a;

哪个实习生调用free()来释放内存。这就是你没有得到任何泄漏的原因。由于分配的内存在g ++中使用free()完全取消分配。

但最佳做法是,如果您使用delete [],则必须使用new []版本。