Topic: Defect Report: basic_string's const method c_str() can invalidate references/iterators
Author: kanze@gabi-soft.fr
Date: Fri, 10 Oct 2003 01:17:51 +0000 (UTC) Raw View
terekhov@web.de (Alexander Terekhov) wrote in message
news:<3F82893E.D05AB97D@web.de>...
> kanze@gabi-soft.fr wrote:
> [...]
> > In fact, there is no requirement that the
> > backing store be contiguous. However, the pointer returned by data or
> > c_str must point to a contiguous buffer. There are several ways to
> > achieve this using a non contiguous backing store; one is to simply
> > switch to contiguous backing store when either of these functions are
> > called. If the iterators also point into the backing store, this will
> > invalidate them.
> This will also make it impossible to call c_str()/data() CONCURRENTLY
> with respect to {almost} any other CONST operation on the same object.
That's not a problem for the standard -- in the standard, there is no
concurrency:-).
Seriously, of course, that is a general problem. In the case of string,
it is explicitly desired, but I see nothing in the standard forbidding
an implementation of any standard class from using mutable members. And
anything which uses mutable members, or casts away const, potentially
has this problem.
It looks like there's one more thing that authors have to document when
they write a class.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orient e objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Ryan Myers" <root@poweredbyg.nu>
Date: Sat, 4 Oct 2003 16:28:37 +0000 (UTC) Raw View
This DR concerns a contradiction in ISO/IEC IS 14882:1998(E) between section
21.3 [lib.basic.string] paragraph 5, and section 21.3.6 [lib.string.ops]
paragraph 1.
In 21.3 paragraph 5 (p384), the Standard states:
"References, pointers, and iterators referring to the elements of a
basic_string sequence may be invalidated by the following uses of that
basic_string object:
...
Calling data() and c_str() member functions."
However, in 21.3.6 paragraph 1 (p397), both c_str() and data() are defined
as being const. By the definition of const, both methods should be
incapable of invalidating iterators.
As most libc implementations simply have said methods return a pointer to
the string's backing store, this is not an active problem; however, it is an
inconsistency. It is capable of producing difficult-to-track bugs in
functions that pass strings by const reference; the callee is capable of
invalidating iterators/references used in the caller, breaking
encapsulation.
The most reasonable fix appears to be modifying 21.3 to remove the ability
of data() and c_str() to invalidate. This does not break existing code; it
is an increase in the promises offered by the standard, while still allowing
for string implementations that use shared backing pools for performance.
Thanks,
~ Ryan Myers <root@poweredbyg.nu>
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: belvis@pacbell.net (Bob Bell)
Date: Sun, 5 Oct 2003 06:11:58 +0000 (UTC) Raw View
"Ryan Myers" <root@poweredbyg.nu> wrote in message news:<IBELIFJHMFFBNDILAFIGKEGPCJAA.root@poweredbyg.nu>...
> This DR concerns a contradiction in ISO/IEC IS 14882:1998(E) between section
> 21.3 [lib.basic.string] paragraph 5, and section 21.3.6 [lib.string.ops]
> paragraph 1.
>
> In 21.3 paragraph 5 (p384), the Standard states:
>
> "References, pointers, and iterators referring to the elements of a
> basic_string sequence may be invalidated by the following uses of that
> basic_string object:
> ...
> ? Calling data() and c_str() member functions."
>
> However, in 21.3.6 paragraph 1 (p397), both c_str() and data() are defined
> as being const. By the definition of const, both methods should be
> incapable of invalidating iterators.
I don't see why const members should not invalidate iterators. Since
this assertion is the foundation of the report, I don't think there's
a defect here.
Bob
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: fap@fap.com ("Anaravescio")
Date: Sun, 5 Oct 2003 18:54:55 +0000 (UTC) Raw View
"Bob Bell" <belvis@pacbell.net> wrote:
> I don't see why const members should not invalidate iterators. Since
> this assertion is the foundation of the report, I don't think there's
> a defect here.
The only way said methods can invalidate references, pointers, or iterators
is if you're modifying the internal state of the string, moving the backing
store; by definition, this is something a const member function should be
incapable of doing, since its this ptr is const. (Can anyone think of a
situation where you could invalidate references WITHOUT modifying the
string's state?) But to illustrate why this makes bugs hard to track,
here's a small degenerate example:
void wraps_some_c_function(char c, const string & str)
{
...
frob(c, str.c_str());
...
}
void parse(string input)
{
for (string::iterator i = input.begin(); i != input.end(); ++i)
{
wraps_some_c_function(*i, input);
}
}
Since the argument to wraps_some_c_function() is const, we're allowed to
call c_str(), and it'll work as expected; however, the behavior of parse()
after it returns will be undefined. This bug can be hard to track down,
especially if the c_str() call is buried eight or nine function levels deep.
It's just as problematic if any callers up the chain have any references
from, say, a call to input[i] lying around.
~ Ryan Myers root@poweredbyg.nu
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net (James Kuyper)
Date: Tue, 7 Oct 2003 00:46:07 +0000 (UTC) Raw View
fap@fap.com ("Anaravescio") wrote in message news:<3f7fc900$1@nntp0.pdx.net>...
> "Bob Bell" <belvis@pacbell.net> wrote:
>
> > I don't see why const members should not invalidate iterators. Since
> > this assertion is the foundation of the report, I don't think there's
> > a defect here.
>
> The only way said methods can invalidate references, pointers, or iterators
> is if you're modifying the internal state of the string, moving the backing
> store; by definition, this is something a const member function should be
> incapable of doing, since its this ptr is const.
That's not true if the object contains a mutable member, or a pointer
to a non-const object.
> ... (Can anyone think of a
> situation where you could invalidate references WITHOUT modifying the
> string's state?)
Yes, by changing the state of an object pointed at by a pointer which
is part of the string's state.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.fr
Date: Tue, 7 Oct 2003 00:46:21 +0000 (UTC) Raw View
"Ryan Myers" <root@poweredbyg.nu> wrote in message
news:<IBELIFJHMFFBNDILAFIGKEGPCJAA.root@poweredbyg.nu>...
> This DR concerns a contradiction in ISO/IEC IS 14882:1998(E) between
> section 21.3 [lib.basic.string] paragraph 5, and section 21.3.6
> [lib.string.ops] paragraph 1.
> In 21.3 paragraph 5 (p384), the Standard states:
> "References, pointers, and iterators referring to the elements of a
> basic_string sequence may be invalidated by the following uses of that
> basic_string object:
> ...
> ? Calling data() and c_str() member functions."
> However, in 21.3.6 paragraph 1 (p397), both c_str() and data() are
> defined as being const. By the definition of const, both methods
> should be incapable of invalidating iterators.
I fail to see any relationship. If the standard says that they may
invalidate iterators, they may invalidate iterators. If the standard
says they may not, they may not. Const has nothing to do with it.
> As most libc implementations simply have said methods return a pointer
> to the string's backing store,
But this is not required. In fact, there is no requirement that the
backing store be contiguous. However, the pointer returned by data or
c_str must point to a contiguous buffer. There are several ways to
achieve this using a non contiguous backing store; one is to simply
switch to contiguous backing store when either of these functions are
called. If the iterators also point into the backing store, this will
invalidate them.
> this is not an active problem; however, it is an inconsistency. It is
> capable of producing difficult-to-track bugs in functions that pass
> strings by const reference; the callee is capable of invalidating
> iterators/references used in the caller, breaking encapsulation.
In general, iterators which can be invalidated can cause difficult to
track bugs. That's part of the philosophy of the STL.
> The most reasonable fix appears to be modifying 21.3 to remove the
> ability of data() and c_str() to invalidate. This does not break
> existing code; it is an increase in the promises offered by the
> standard, while still allowing for string implementations that use
> shared backing pools for performance.
To be frank, I'm not too sure what we should do with std::string. The
current interface doesn't allow efficient implementations anyway, so
maybe we should just go the full route, more or less impose a specific
implementation, and accept the fact that anyone needing an efficient
string will have to write their own.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orient e objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: johnchx2@yahoo.com (johnchx)
Date: Tue, 7 Oct 2003 00:46:29 +0000 (UTC) Raw View
fap@fap.com ("Anaravescio") wrote i
>
> > I don't see why const members should not invalidate iterators. Since
> > this assertion is the foundation of the report, I don't think there's
> > a defect here.
>
> The only way said methods can invalidate references, pointers, or iterators
> is if you're modifying the internal state of the string, moving the backing
> store; by definition, this is something a const member function should be
> incapable of doing, since its this ptr is const.
std::strings are allowed to have mutable members.
I suspect that the reason for allowing a string to invalidate
iterators in this situation is to permit an implementation with a
non-contiguous backing store which "re-arranges" itself into a
contiguous buffer when data() or c_str() is called.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]