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. 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. * `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, * Howard Hinnant's help and advices were essential when implementing move semantics,
improving allocator support or implementing small string optimization. Thanks Howard 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/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/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/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/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://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]]. * [@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); old_values_destroyer.shrink_forward(new_size-s_before);
this->m_holder.m_size = new_size; this->m_holder.m_size = new_size;
//Now move remaining last objects in the old buffer begin //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 //Once moved, avoid calling the destructors if trivial after move
if(value_traits::trivial_dctr_after_move){ if(value_traits::trivial_dctr_after_move){
old_values_destroyer.release(); old_values_destroyer.release();
@@ -3246,8 +3249,9 @@ class vector
const size_type rest_new = n - mid_n; const size_type rest_new = n - mid_n;
insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, rest_new); insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, rest_new);
T* const move_start = old_start + rest_new; T* const move_start = old_start + rest_new;
//Displace old_end //Displace old_end, but make sure data has to be moved
T* const move_end = ::boost::container::move(pos, old_finish, move_start); 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 //Destroy remaining moved elements from old_end except if they
//have trivial destructor after being moved //have trivial destructor after being moved
size_type n_destroy = s_before - n; size_type n_destroy = s_before - n;