我使用valgrind
和--leak-check=full
检查了C ++中的以下代码,并且没有内存泄漏。那是为什么?
char *p = new char[256];
delete p;
据我所知, new[]
应与delete[]
匹配。
答案 0 :(得分:38)
尽管@KillianDS说它是未定义的行为,但差异可能与delete
和delete[]
释放底层内存的事实有关。 delete[]
的要点是在释放内存之前调用数组中每个对象的析构函数。由于char
是POD并且没有析构函数,因此在这种情况下两者之间没有任何有效差异。
然而,你绝对不应该依赖它。
答案 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)
delete
和delete []
之间的区别在于编译器添加了代码来调用删除对象的析构函数。说这样的话:
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 []
版本。