https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110620

--- Comment #8 from Jonathan Wakely <redi at gcc dot gnu.org> ---
That isn't necessarily true though. _S_check_init_len takes __n by non-const
reference and changes it to be the number of elements that are actually
allocated *which might be more than requested*. std::vector has to grow
exponentially, so if the current size is 10 and we ask for 12, it will actually
allocate space for 20, and set __n to 20.

So the end_of_storage is start + 20, but finish is start + 12

We could make a copy of __n before the call to _S_check_init_len, and then use
that:

          const size_type __orig_n = __n;
          pointer __start = this->_M_impl._M_start =
            this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator()));
          this->_M_impl._M_end_of_storage = __start + __n;
          this->_M_impl._M_finish
              = std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last,
                                            __start, _M_get_Tp_allocator());
          if (this->_M_impl._M_finish - this->_M_impl._M_start != __orig_n)
            __builtin_unreachable();


Or equivalently, let _S_check_init_len write to a different variable:

          size_type __n_allocated = __n;
          pointer __start = this->_M_impl._M_start =
            this->_M_allocate(_S_check_init_len(__n_allocated,
_M_get_Tp_allocator()));
          this->_M_impl._M_end_of_storage = __start + __n_allocated;
          this->_M_impl._M_finish
              = std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last,
                                            __start, _M_get_Tp_allocator());
          if (this->_M_impl._M_finish - this->_M_impl._M_start != __n)
            __builtin_unreachable();

Reply via email to