[RFC] Strange line at the end of _M_mutate

Nathan Myers ncm-nospam@cantrip.org
Sun Dec 16 11:34:00 GMT 2001


On Sun, Dec 16, 2001 at 05:37:27PM +0100, Paolo Carlini wrote:
> today, while preparing two more testcases for basic_string::assign
> I noticed what seems to a me discrepancy. At the beginning of
> basic_string.h, a comment says:
> 
>   //   1. String really contains _M_length + 1 characters; last is set
>   //      to 0 only on call to c_str().  We avoid instantiating
>   //      _CharT() where the interface does not require it.

This was a design principle maintained for most of the lifetime
of basic_string<>, pre-standardization.  
 
> And this is consistent with the implementation of c_str() below.
> 
> However, _M_mutate (in basic_string.tcc) ends with:
> 
>       _M_data()[__new_size] = _Rep::_S_terminal; // grrr. (per 21.3.4)
>     // You cannot leave those LWG people alone for a second.

At the last meeting before the standard was released, while I was not 
present, the LWG elected to abandon the principle in order to allow 
overindexing strings by one character, to "preserve" C-like code that 
relies on a null sentinel rather than checking the string index.

It was one of a series of radical changes adopted on the flimsiest of
premises at the last minute, sacrificing all the care that had gone
into the earlier decisions.  
 
> Now, I cannot find a reference to any relevant issue in 21.3.4 and this
> line seems to me not consistent with the comment above.
> 
> It is ironic that, were not for this line in _M_mutate, libstdc++/4354
> would not be a bug, *at least* for the implementation of memcopy
> I'm using (glibc2.2.4): if _M_mutate would not put that termination
> char at the end of the _Rep, otherwise _S_copy_chars (i.e., memcopy)
> is able to deal with the *specific* copy pattern necessary for
> basic_string::assign correctly, as if it were a memmove.
>
> Of course, the real problem with overlapping ranges would have
> surfaced soon with replace (we have at least one testcase in the
> testsuite which gcc-3_0 cannot pass even stripping that line from
> _M_mutate).
>
> Anyway, do you believe that the final line in _M_mutate is bogus? In
> that case, perhaps those two testcases I prepared are not so relevant
> and _M_mutate should be patched instead...

The first comment is obsolete; the requirement is now that _CharT()
appear whenever s[s.size()] is examined, regardless of the cost.

The only saving grace is that the effect of actually storing a non-null 
there is undefined, and is allowed to crash their program.  In practice, 
we probably have to sprinkle checks in various places to throw if we 
find it violated.  I hope this doesn't mean checking every iterator
and indexing operation.

Nathan Myers
ncm at cantrip dot org



More information about the Libstdc++ mailing list