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

Dan*_*can 29 c++ valgrind memory-leaks

我使用valgrindwith 检查了C++中的以下代码--leak-check=full,它说没有内存泄漏.这是为什么?

char *p = new char[256];
delete p;
Run Code Online (Sandbox Code Playgroud)

new[]delete[]据我所知应该匹配.

Jon*_*ter 38

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

但是,你绝对不应该依赖它.

  • 使用非平凡的析构函数,`delete`将崩溃,因为它存储了数组开头的元素计数,因此指针不等于底层的`free`所期望的,而'free`会引发致命的断言.不同的编译器和标准C++库的表现不同,但AFAIR gcc就是这样做的. (2认同)

小智 12

delete并且delete[]仅当p指向基本数据类型时才相等,例如char或int.

如果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;
}
Run Code Online (Sandbox Code Playgroud)

通过使用delete[]数组中的所有析构函数将被调用.通过使用delete只有p[0]的析构函数将被调用.

  • 或者它可能会崩溃并使你的PC无法运行,毕竟它是未定义的行为.根据实现`new []`可以使用分配缓冲区的前8个字节来存储元素的数量,然后在缓冲区内返回一个偏移量; 在这种情况下,`delete`会将offseted地址传递给`free`,这可能会导致`free`找不到相应的缓冲区... (3认同)

asc*_*ler 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)
Run Code Online (Sandbox Code Playgroud)

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


Yu *_*Hao 7

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