Valgrind不报告“删除阵列”上的内存泄漏

时间:2012-05-14 15:11:10

标签: c++ memory-leaks valgrind delete-operator

在实现下面的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;
}

2 个答案:

答案 0 :(得分:7)

使用delete而不使用[]会导致内存泄漏。

不,它会导致未定义的行为

使用new []分配的程序和使用delete解除分配的程序具有未定义的行为。实际上,你很幸运(相当不幸)它没有表现出一些奇怪的行为。

作为旁注,您还需要关注班级的 Rule of Three 。目前,您不会这样做,并且在不久的将来会遇到麻烦。

答案 1 :(得分:2)

deletedelete[]之间的主要区别不在于内存释放,而在于析构函数调用。

虽然正式未定义的行为,但在实践中它或多或少会起作用......除了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