Valgrind does not report memory leak on “delete ar

2020-03-31 16:35发布

问题:

After implementing the C++ code below, I ran valgrind --leak-check=full in order to check if there was any memory leak. The result was 0 bytes were in use at exit and no leaks are possible.

However, later I discovered that I've forgotten to use delete[] x instead of just delete x inside the destructor.

I searched for some explanations (for instance: delete vs delete[] operators in C++), and everything I read said that using delete without [] can cause memory leak, since it calls just the destructor for the first object in the array.

I changed the code to delete[] and the valgrind output was the same (as expected). But now I'm confused: "Is there a problem with valgrind, or does delete really works fine for arrays even without the operator []?"

#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;
}

回答1:

using delete without [] causes memory leak.

No, it causes Undefined Behavior.

Your program where you allocate using new [] and deallocate using delete has Undefined Behavior. Actually, you are lucky(rather unlucky) it doesn't show some weird behavior.

As a side note, You also need to follow the Rule of Three for your class. Currently, you don't do so and are calling for trouble in near future.



回答2:

The main difference between delete and delete[] is not about memory deallocation, but about destructor calls.

While formally undefined behavior, in practice it will more or less work... except that delete will only call the destructor of the first item.

As a side note, you may get an issue:

#include <iostream>

struct A{
  ~A() { std::cout << "destructor\n"; }
};

int main() {
  A* a = new A[10];
  delete a;
}

a bit like:

*** 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: ========

See it at ideone.