2

I have read multiple similar questions on the same topic that have been asked, but I was not able to resolve my issue by following them.

I want to store pointers in a vector, but I see a memory leak. My code is as follows.

#include <iostream>
#include <vector>
#include <memory>

class Base 
{
    public:
       virtual ~Base() {}
};

class Derived : public Base {};

std::vector<std::unique_ptr<Base>> bv;

int main()
{
    for (int i = 0; i < 10; i++)
       bv.emplace_back(std::make_unique<Base>(Derived()));

    bv.clear();

    return 0;
}

Valgrind reports: "still reachable: 72,704 bytes in 1 blocks". I have the same issue if I don't use unique_ptr, and just use bv.emplace_back(new Derived);, and delete the pointers explicitly from the vector. What is causing the leak?

Justin
  • 24,288
  • 12
  • 92
  • 142
Sayan
  • 2,662
  • 10
  • 41
  • 56

1 Answers1

5

Looks like you actually store instances of Base class. Derived() creates an object on the stack and then make_unique passes it to the constructor of Base. This is object slicing. This won't explain the leak but indicates the code may not do what you expect.

ADDITION: DELETED: free() doesn't always return memory back to the system. Libc will keep this memory for future malloc(). This probably explains your observation.

I agree with @cmaster's comment below. Valgrind does keep track of malloc/free. After a bit of research I found another question on stackoverflow which explains the observation.

include iostream

"Many implementations of the C++ standard libraries use their own memory pool allocators." They just don't free their memory.

More details: Valgrind: Memory still reachable with trivial program using <iostream>

Sergei
  • 508
  • 7
  • 13
  • I want to store instances of Base class. In my real application, the derived class is templated, and since I need to access it later (when I won't know the template), I store a non-templated pointer to base class. – Sayan Aug 02 '17 at 20:19
  • 1
    @Sayan my comment was based on your example. It's hard to see why you would want to have object slicing in your code. – Sergei Aug 02 '17 at 20:24
  • Yes, I agree with you. – Sayan Aug 02 '17 at 20:28
  • 3
    `free()` may not return memory to the system, but `valgrind` keeps track on what is returned from `malloc()` and what is passed into `free()` anyway. After all, valgrind actually runs the program on a simulated CPU, it's not just listening on the syscalls as `strace` does. So, the implementation details are definitely not the answer to this question. – cmaster - reinstate monica Aug 02 '17 at 21:19