string::assign apparent regression

Paolo Carlini pcarlini@unitus.it
Fri Sep 14 11:31:00 GMT 2001


Hi Roberto, hi all,

in the last hour, with the help of GDB I tried to understand in some
detail your testcase, after having verified that indeed 3 other reference
implementations of the C++ library behave as you expected ;-)

I traced back the problem not to a wrong terminator, but to the following
function in basic_string.tcc (lines 442-462):

--------------------------------------

  template<typename _CharT, typename _Traits, typename _Alloc>
    template<typename _ForwardIter>
      basic_string<_CharT, _Traits, _Alloc>&
      basic_string<_CharT, _Traits, _Alloc>::
      _M_replace(iterator __i1, iterator __i2, _ForwardIter __k1,
   _ForwardIter __k2, forward_iterator_tag)
      {
 size_type __dold = __i2 - __i1;
 size_type __dmax = this->max_size();
 size_type __dnew = static_cast<size_type>(distance(__k1, __k2));

 if (__dmax <= __dnew)
   __throw_length_error("basic_string::_M_replace");
 size_type __off = __i1 - _M_ibegin();
 _M_mutate(__off, __dold, __dnew);
 // Invalidated __i1, __i2
 if (__dnew)
   _S_copy_chars(_M_data() + __off, __k1, __k2);

 return *this;
      }

---------------------------------------

What happens is that _M_mutate(__off, __dold, __dnew) is called with
__dold = 41 and __dnew = 23 *before* the actual copy operation
(_S_copy_chars) is carried out. Since the destination and source is the
very same string (i.e., aux) in your testcase, the aux string (as source)
is truncated at the 23th character ("../BenchCtiTr/apt/merge") and the
following copy operation (_S_copy_chars) produces a final aux = "merge".

Indeed, tentatively exchanging the _M_mutate and _S_copy_chars leads to
the expected behavior.

So, the trivial workaround is temporarily copying (aux, i+1,
string::npos) to a dummy string and then copying it back in aux. On the
other hand, the current structure of _M_replace should be heavily
modified if the current behaviouf of libstdc++-v3 is really incorrect wrt
the ISO standard.


Cheers,
Paolo.




More information about the Libstdc++ mailing list