aclements / libelfin

C++11 ELF/DWARF parser
MIT License
314 stars 99 forks source link

dwarf/small_vector.hh destructs new buffer on calls to reserve() #36

Open 4onen opened 5 years ago

4onen commented 5 years ago

Hi! I've been working on the memory leak in relation to one of my own projects and stumbled across this bizarre behavior in the small_vector.hh class used by the dwarf folder of libelfin.

Specifically, calls to small_vector::reserve() will cause the small_vector to copy the objects in its buffer, destroy the newly copied objects, then release the old buffer (of not-yet-destroyed objects.)

I built a few tests to examine the issue, and check whether this was in-fact proper use of placement-new. (It doesn't appear to be.)

test.cpp makes this behavior minimally apparent, by removing the rest of the small_vector.hh file and just performing the problematic operations in reserve, specifically within the "reserve2" section.

test_their.cpp uses the unmodified small_vector.hh class to show the exact same behavior as test.cpp.

test_mine.cpp uses small_vector_fixed.hh which changes the problematic destruction to destroy the objects in the old buffer and, if available on the type T, uses move semantics to relocate the objects in the buffer.

All tests work on a type A which simply marks its ID in order of construction, its validity under C++ object lifetimes, whether it was copy constructed, whether it was moved-into, and whether it was moved-from.

tl;dr: small_vector.hh runs destructors on the new buffer on reserve() calls instead of the old one. small_vector_fixed.hh in this tests archive doesn't do that, and will std::move the Ts if they have move semantics.

Starkeus commented 8 months ago

++ on this issue.