0

I have used pointers to create an array and then wrote a delete procedure in the destructor

class cBuffer{
  private:
    struct entry {
      uint64_t key;
      uint64_t pc;
    };
    entry *en;
  public:
    cBuffer(int a, int b, int mode)
    {
      limit = a;
      dist = b;
      md = mode;
      en = new entry[ limit ];
      for (int i=0; i<limit; i++) {
        en[i].key = 0;
        en[i].pc = 0;
      }
    };
    ~cBuffer() { delete [] en; }
    ...
   }

In another class I use cBuffer like this:

class foo() {
   cBuffer *buf;
   foo()
   {
     buf = new cBuffer(gSize, oDist, Mode);
   }
};

However, valgrind complains about the new operator

==20381== 16,906,240 bytes in 32 blocks are possibly lost in loss record 11,217 of 11,221
==20381==    at 0x4A0674C: operator new[](unsigned long) (vg_replace_malloc.c:305)
==20381==    by 0x166D92F8: cBuffer::cBuffer(int, int, int) 
mahmood
  • 23,197
  • 49
  • 147
  • 242
  • 4
    You did not follow the Rule of three. – Alok Save Apr 28 '13 at 14:37
  • See: https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming) – Paul R Apr 28 '13 at 14:40
  • @mahmood: See [here](http://stackoverflow.com/questions/4172722); if you're managing a resource and releasing it in the destructor, then you almost certainly need to implement or delete the copy constructor and copy-assignment operator, otherwise you can end up with two objects both trying to release the same resource. – Mike Seymour Apr 28 '13 at 14:41
  • 1
    But that's unlikely to be the cause of a memory leak; how are you creating and destroying the `cBuffer` object? My best guess is that you're leaking the whole object with a `new cBuffer` and no corresponding `delete`. – Mike Seymour Apr 28 '13 at 14:41
  • 2
    You're using naked pointers. You shouldn't. – Kerrek SB Apr 28 '13 at 14:45
  • @mahmood: and what happens when `foo` is destroyed? – Mat Apr 28 '13 at 14:48
  • Why are you storing the `cBuffer` on the free store? – Yakk - Adam Nevraumont Apr 28 '13 at 14:50
  • @Mat: I understand that you may say I have to include `delete buf` in `~foo()`. But does that really matters? If that is the case, valgrind should point there and not the cBuffer itself – mahmood Apr 28 '13 at 14:50
  • 2
    @mahmood: I would expect valgrind to report both leaks. Are you saying it only reports that one? – Mike Seymour Apr 28 '13 at 14:53
  • @Mike Seymour: Yes you are right. I scrolled one by one and saw cBuffer first! – mahmood Apr 28 '13 at 14:54

2 Answers2

2
 cBuffer *buf;
   foo()
   {
     buf = new cBuffer(gSize, oDist, Mode);
   }

You need to call

delete buf;

Since you explicitly called new

Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

Your class foo will cause your leak, since you never delete the dynamically allocated cBuffer. The solution is simple: there's no need for dynamic allocation at all here.

class foo {
    cBuffer buf;  // An object, not a pointer
    foo() : buf(gSize, oDist, Mode) {}
};

More generally, when you do need dynamic allocation, be careful that you always delete what you new. The most reliable way to do this is to use RAII types such as containers and smart pointers to manage all dynamic resources for you.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • The reason why I used pointers is discussed here http://stackoverflow.com/questions/15922760/creating-an-object-in-the-constructor-or-an-init-function – mahmood Apr 28 '13 at 14:53
  • @mahmood: I don't see any discussion of pointers there, just some bad advice telling you to use a pointer when you don't need to, and some better advice telling you not to. – Mike Seymour Apr 28 '13 at 14:54