Fixes Trac #11912: "flat_map use of vector::priv_forward_range_insert_expand_backwards may cause move with same source"

This commit is contained in:
Ion Gaztañaga
2016-02-24 22:27:53 +01:00
parent 310d8eaf10
commit 3e82a27917
2 changed files with 9 additions and 4 deletions

View File

@@ -1200,7 +1200,7 @@ use [*Boost.Container]? There are several reasons for that:
then adapted for [*Boost.Interprocess]. Thanks for such a great container.
* `static_vector` was based on Andrew Hundt's and Adam Wulkiewicz's high-performance `varray` class.
Many performance improvements of `vector` were also inspired in their implementation. Thanks!
Many performance improvements of `vector` were also inspired by their implementation. Thanks!
* Howard Hinnant's help and advices were essential when implementing move semantics,
improving allocator support or implementing small string optimization. Thanks Howard
@@ -1221,6 +1221,7 @@ use [*Boost.Container]? There are several reasons for that:
* [@https://svn.boost.org/trac/boost/ticket/11856 Trac #11856 : ['"pool_resource.cpp error: declaration changes meaning"]].
* [@https://svn.boost.org/trac/boost/ticket/11866 Trac #11866 : ['"small_vector does not have range constructor"]].
* [@https://svn.boost.org/trac/boost/ticket/11867 Trac #11867 : ['"small_vector should have constructor and assignment operator taking other small_vector"]].
* [@https://svn.boost.org/trac/boost/ticket/11912 Trac #11912 : ['"flat_map use of vector::priv_forward_range_insert_expand_backwards may cause move with same source"]].
* [@https://svn.boost.org/trac/boost/ticket/11957 Trac #11957 : ['"static_vector::max_size() is higher than the capacity"]].
* [@https://svn.boost.org/trac/boost/ticket/12014 Trac #12014 : ['"boost::container::set can not insert const (ref) range"]].
* [@https://github.com/boostorg/container/pull/33 GitHub #33: ['Make sure std::string constructor is available]].

View File

@@ -3106,7 +3106,10 @@ class vector
old_values_destroyer.shrink_forward(new_size-s_before);
this->m_holder.m_size = new_size;
//Now move remaining last objects in the old buffer begin
::boost::container::move(pos + raw_gap, old_finish, old_start);
T * const remaining_pos = pos + raw_gap;
if(remaining_pos != old_start){ //Make sure data has to be moved
::boost::container::move(remaining_pos, old_finish, old_start);
}
//Once moved, avoid calling the destructors if trivial after move
if(value_traits::trivial_dctr_after_move){
old_values_destroyer.release();
@@ -3246,8 +3249,9 @@ class vector
const size_type rest_new = n - mid_n;
insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, rest_new);
T* const move_start = old_start + rest_new;
//Displace old_end
T* const move_end = ::boost::container::move(pos, old_finish, move_start);
//Displace old_end, but make sure data has to be moved
T* const move_end = move_start != pos ? ::boost::container::move(pos, old_finish, move_start)
: old_finish;
//Destroy remaining moved elements from old_end except if they
//have trivial destructor after being moved
size_type n_destroy = s_before - n;