[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