Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#8977 closed Bugs (fixed)

Memory leak in boost::heap::fibonacci_heap when used with boost::shared_ptr and default allocator

Reported by: Wolf A. Heidrich <wolf.heidrich@…> Owned by: timblechmann
Milestone: To Be Determined Component: heap
Version: Boost 1.54.0 Severity: Problem
Keywords: Cc:

Description

There is a bad possible memory leak in the fibonacci_heap when it is used with the default allocator and boost::shared_ptr.

Example code:

#include <boost/heap/fibonacci_heap.hpp>
#include <boost/shared_ptr.hpp>

int main(int argc, char* argv[])
{
    boost::heap::fibonacci_heap<boost::shared_ptr<int> > heap;
    heap.push(boost::shared_ptr<int>(new int(0)));

    return 0;
}

Valgrind says:

==8228== HEAP SUMMARY:
==8228==     in use at exit: 28 bytes in 2 blocks
==8228==   total heap usage: 650 allocs, 648 frees, 105,755 bytes allocated
==8228== 
==8228== 28 (24 direct, 4 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==8228==    at 0x4C2BCA7: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==8228==    by 0x4080A3: boost::detail::shared_count::shared_count<int>(int*) (shared_count.hpp:91)
==8228==    by 0x407E05: boost::shared_ptr<int>::shared_ptr<int>(int*) (shared_ptr.hpp:183)
==8228==    by 0x40794D: main (SandBox.cpp:99)
==8228== 
==8228== LEAK SUMMARY:
==8228==    definitely lost: 24 bytes in 1 blocks
==8228==    indirectly lost: 4 bytes in 1 blocks
==8228==      possibly lost: 0 bytes in 0 blocks
==8228==    still reachable: 0 bytes in 0 blocks
==8228==         suppressed: 0 bytes in 0 blocks
==8228== 
==8228== For counts of detected and suppressed errors, rerun with: -v
==8228== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)

The problem is the line

alloc_.deallocate(n, 1);

in the struct node_disposer in heap_node.hpp.

It does what it says: If it is a std::allocator which the boost::heap::allocator<> defaults to if not specified, it deallocates the memory but it does not call destructors as internally ::operator delete() is called on the heap_node. That means that every object that has been pushed into the heap does not get its destructor called.

Obviously this is really bad when using a boost::shared_ptr because the use_count will not go to 0. Using a boost::weak_ptr is not a remedy as the boost::shared_ptr's shared_count object that is on the heap will not get deleted as the boost::weak_ptr's destructor is not called and thus the boost::shared_ptr's weak_count does not go to 0.

I did not check whether this problem affects the other heaps as well.

Change History (2)

comment:1 by timblechmann, 9 years ago

Resolution: fixed
Status: newclosed

(In [85250]) heap: fix memory leak in destructor

fixes #8977

comment:2 by Joel Young <jdy@…>, 9 years ago

When is this fix going to be committed? It isn't checked in to git: git clone --recursive https://github.com/boostorg/boost.git

Note: See TracTickets for help on using tickets.