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