在实现下面的C ++代码之后,我运行valgrind --leak-check=full
以检查是否存在任何内存泄漏。结果是 0字节在退出时使用并且没有泄漏可能。
然而,后来我发现我忘记在析构函数中使用delete[] x
而不是delete x
。
我搜索了一些解释(例如:delete vs delete[] operators in C++),我读到的所有内容都表明使用delete
而不使用[]
会导致内存泄漏,因为它只调用了析构函数数组中的第一个对象。
我将代码更改为delete [],并且valgrind输出相同(如预期的那样)。但现在我很困惑:“valgrind有问题,或者delete
是否真的适用于数组,即使没有运算符[]
?”
#include <iostream>
#include <string.h>
using namespace std;
class Foo {
private: char *x;
public:
Foo(const char* px) {
this->x = new char[strlen(px)+1];
strcpy(this->x, px);
}
~Foo() {
delete x;
}
void printInfo() { cout << "x: " << x << endl; }
};
int main() {
Foo *objfoo = new Foo("ABC123");
objfoo->printInfo();
delete objfoo;
return 0;
}
答案 0 :(得分:7)
使用delete而不使用[]会导致内存泄漏。
不,它会导致未定义的行为。
使用new []
分配的程序和使用delete
解除分配的程序具有未定义的行为。实际上,你很幸运(相当不幸)它没有表现出一些奇怪的行为。
作为旁注,您还需要关注班级的 Rule of Three 。目前,您不会这样做,并且在不久的将来会遇到麻烦。
答案 1 :(得分:2)
delete
和delete[]
之间的主要区别不在于内存释放,而在于析构函数调用。
虽然正式未定义的行为,但在实践中它或多或少会起作用......除了delete
只会调用第一个项目的析构函数。
作为旁注,您可能会遇到问题:
#include <iostream>
struct A{
~A() { std::cout << "destructor\n"; }
};
int main() {
A* a = new A[10];
delete a;
}
有点像:
*** glibc detected *** ./prog: munmap_chunk(): invalid pointer: 0x093fe00c ***
======= Backtrace: =========
/lib/libc.so.6[0xb759dfd4]
/lib/libc.so.6[0xb759ef89]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/libstdc++.so.6(_ZdlPv+0x21)[0xb77602d1]
./prog(__gxx_personality_v0+0x18f)[0x8048763]
./prog(__gxx_personality_v0+0x4d)[0x8048621]
======= Memory map: ========
请见ideone。