[Boost-bugs] [Boost C++ Libraries] #13500: Memory leak when using erase on string vectors

Subject: [Boost-bugs] [Boost C++ Libraries] #13500: Memory leak when using erase on string vectors
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2018-03-29 11:25:03


#13500: Memory leak when using erase on string vectors
------------------------------+---------------------------
 Reporter: anonymous | Owner: Ion Gaztañaga
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: container
  Version: Boost 1.58.0 | Severity: Problem
 Keywords: |
------------------------------+---------------------------
 Consider the following example:

 {{{

 #include <boost/container/vector.hpp>
 #include <boost/container/string.hpp>

 int main() {
   boost::container::vector<boost::container::string> myVec;

 // myVec.push_back("Short string");
   myVec.push_back("This is a long string that exceeds a certain threshold
 (23 in my case)");
   myVec.erase(myVec.begin());

   return 0;
 }

 }}}

 When running this example and pushing back the long string, valgrind
 reports a memory leak (see attached file). When using the short string,
 there is no leak. I assume this has to do with the boost short string
 optimization, which puts shorter strings into a buffer living in stack
 instead of allocating a buffer on the heap.

 Also, when I do not erase(..) the element but let the vector destructor
 clean up the memory, there is no leak.

 Looking at the implementation of vector's erase(..):

 {{{

    //! <b>Effects</b>: Erases the element at position pos.
    //!
    //! <b>Throws</b>: Nothing.
    //!
    //! <b>Complexity</b>: Linear to the elements between pos and the
    //! last element. Constant if pos is the last element.
    iterator erase(const_iterator position)
    {
       BOOST_ASSERT(this->priv_in_range(position));
       const pointer p = vector_iterator_get_ptr(position);
       T *const pos_ptr = boost::movelib::to_raw_pointer(p);
       T *const beg_ptr = this->priv_raw_begin();
       T *const new_end_ptr = ::boost::container::move(pos_ptr + 1, beg_ptr
 + this->m_holder.m_size, pos_ptr);
       //Move elements forward and destroy last
       this->priv_destroy_last(pos_ptr == new_end_ptr);
       return iterator(p);
 }
 }}}

 I think the condition passed as argument to priv_destroy_last(const bool
 moved) has to be negated? pos_ptr == new_end_ptr is fulfilled if
 ::boost::container::move has NOT moved anything.

-- 
Ticket URL: <https://svn.boost.org/trac10/ticket/13500>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2018-03-29 11:30:42 UTC