1

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;
}
Community
  • 1
  • 1
Moacir Ponti
  • 591
  • 5
  • 14
  • The answers to the question you linked to make no mention of memory leaks. In fact they say the same thing that Als says below. So why are you saying *"everything I read said that using delete without [] causes memory leak."* ? – Benjamin Lindley May 14 '12 at 15:18
  • 2
    Plus, using valgrind 3.2.1 on your program flags that there is a 'Mismatched free() / delete / delete[]'. It's not a memory leak, but it is an error. – Dave S May 14 '12 at 15:21
  • It is know that, for example, MSVC happens to generate the same code for `delete x` and `delete[] x` when the array contains built in types like `char`. The code is *different* for class types with a destructor. – Bo Persson May 14 '12 at 15:32
  • 1
    Although you're detecting it with a different tool, the code and question here are a possible duplicate of [_CrtMemDumpAllObjectsSince() function is not able to detect leaks if delete array called instead of delete \[\]array](http://stackoverflow.com/questions/10545436/crtmemdumpallobjectssince-function-is-not-able-to-detect-leaks-if-delete-arra) and my answer to that question applies about equally here. – Jerry Coffin May 14 '12 at 15:49
  • Thanks Jerry, I couldn't find this question. The answers there are very interesting – Moacir Ponti May 14 '12 at 16:27

2 Answers2

7

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.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • Couldn't have said it better, but I'll quote the FAQ so the asker can reference what's going on: "It is the programmer's —not the compiler's— responsibility to get the connection between new T[n] and delete[] p correct. If you get it wrong, neither a compile-time nor a run-time error message will be generated by the compiler. Heap corruption is a likely result. Or worse. Your program will probably die." http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.12 – Stephen Newell May 14 '12 at 16:26
  • Stephen, yes, I know it is the programmer's responsibility and I also know the consequences. I just want to understand why valgrind could not find the possible leak. – Moacir Ponti May 14 '12 at 16:29
  • Als, thanks also for the side note. Does undefined behavior means no one can know what will happen? But it is known that heap corruption is very likely (as quoted by Stephen), so why valgrind cannot find it? – Moacir Ponti May 14 '12 at 16:32
  • 1
    @MoacirPontiJr.: Yes Undefined Behavior means anything (quite literally) is possible. Once a program has Undefined Behavior you cannot expect any behavior, all bets are off.Also, as I said in answer the outcome of mismatched `new []` and `delete` is Undefined Behavior which can be a memory leak not necessarily though. – Alok Save May 14 '12 at 16:39
3

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.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • I think that is OP's contention since his `delete` call is in the destructor. – Alok Save May 14 '12 at 15:48
  • Most implementations will (luckily) fail for most types when "delete new T[n]" because they store the size in front of the allocation, thus having slightly offset pointers for the call of the underlying raw memory manager – PlasmaHH May 14 '12 at 15:50