Reputation: 3350
I created this pattern in the project I'm working on:
struct Item {};
struct Base {
struct Result {
std::shared_ptr<Base> base_ptr;
Result(Base * base) : base_ptr(base) {}
};
virtual Base::Result update() const = 0;
};
struct Sub : public Base {
const std::vector<Item> items;
Sub(std::vector<Item> items) : items(items) {}
Base::Result update() const override {
return {new Sub{items}};
}
};
int main() {
std::vector<Item> items{Item{}};
auto base = std::shared_ptr<Base>{new Sub{items}};
auto result = base->update();
}
Which according to valgrind causes a leak in the vector:
==21663== 1 bytes in 1 blocks are definitely lost in loss record 1 of 2
==21663== at 0x4C29158: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==21663== by 0x401DC5: __gnu_cxx::new_allocator<Item>::allocate(unsigned long, void const*) (in /home/user/code/test_leak/a.out)
==21663== by 0x401C64: std::allocator_traits<std::allocator<Item> >::allocate(std::allocator<Item>&, unsigned long) (in /home/user/code/test_leak/a.out)
==21663== by 0x4019D7: std::_Vector_base<Item, std::allocator<Item> >::_M_allocate(unsigned long) (in /home/user/code/test_leak/a.out)
==21663== by 0x401890: std::_Vector_base<Item, std::allocator<Item> >::_M_create_storage(unsigned long) (in /home/user/code/test_leak/a.out)
==21663== by 0x401428: std::_Vector_base<Item, std::allocator<Item> >::_Vector_base(unsigned long, std::allocator<Item> const&) (in /home/user/code/test_leak/a.out)
==21663== by 0x401044: std::vector<Item, std::allocator<Item> >::vector(std::vector<Item, std::allocator<Item> > const&) (in /home/user/code/test_leak/a.out)
==21663== by 0x400EAA: Sub::Sub(std::vector<Item, std::allocator<Item> >) (in /home/user/code/test_leak/a.out)
==21663== by 0x400F4B: Sub::update() const (in /home/user/code/test_leak/a.out)
==21663== by 0x400D02: main (in /home/user/code/test_leak/a.out)
==21663==
==21663== LEAK SUMMARY:
==21663== definitely lost: 1 bytes in 1 blocks
There is no leak if the code is changed to return a shared_ptr instead of Base::Result, but I need to return more than the shared_ptr in order to pass on some messages to the receiver.
If there is a conventional pattern that better solves this problem, then of course I'm interested in that. Otherwise I want to know how to fix the leak by modifying my current code.
Upvotes: 1
Views: 104
Reputation: 35855
You forgot do define virtual destructor in Base
struct:
virtual ~Base() {}
Upvotes: 4