Topic: is a string::iterator safe after modifying the string


Author: Alex <spammers@sod.off>
Date: Mon, 12 Mar 2001 14:27:18 GMT
Raw View
(See bottom for e-mail)
Hi,
I was wondering how safe it is to use an iterator on string after
modifying it.

Example:
bool in_string = false;
string::iterator sit = str.begin();
string::iterator first, last;
for(; sit != str.end() ; ++sit) {
   if(*sit == '"'){
     if(! in_string) {
        first = sit;
        in_string = true;
        continue;
     }
     else {
        last = sit;
        in_string = false;
        str.replace(first,last,replacement_string);
      // is it safe to use sit now?
      // if so, where does it point?
      // if not, what would be the smart way to do it?
    }
  }
}

This stupid example illustrates what I want to do. On gcc 2.95.2 I will
get a segfault and/or exception quit soon, but gcc 2.95.2 also typedefs
a string::iterator as char pointer. What does the standard say about
this?

--
Alex
e-mail: tamm at cs dot helsinki dot fi

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: remove.haberg@matematik.su.se (Hans Aberg)
Date: Mon, 12 Mar 2001 19:51:36 GMT
Raw View
In article <98ilnj$2v5$1@oravannahka.helsinki.fi>, Alex <spammers@sod.off>
wrote:
>I was wondering how safe it is to use an iterator on string after
>modifying it.
...
>string::iterator sit = str.begin();
>string::iterator first, last;
...
>        str.replace(first,last,replacement_string);
>      // is it safe to use sit now?
>      // if so, where does it point?
>      // if not, what would be the smart way to do it?
...

If you modify the string, and especially tries to alter its size, it may
need to create an entirely new memory allocation. Then your iterator
typically will point into unused memory, and it is very nice of your
compiler to point it out to by making a segmentation fault.

Two methods around this comes to my mind: If the replacement string is of
different length (especially longer), then build an entirely new string.
If you need it in place of the old string, I think you can swap them.

Or use STL (style) macros to do the replacements if the replacement string
is of the same size (or shorter). -- If it is shorter, you can chop off
what remains after the replacements are done.

If you are in need of more advanced parsing, pick down Flex & Bison
   ftp://ftp.digital.com/pub/GNU/non-gnu/flex/flex-2.5.4a.tar.gz
   ftp://alpha.gnu.org/gnu/cvs/
and compile the output the produce as C++.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: James Kanze <kanze@gabi-soft.de>
Date: Tue, 13 Mar 2001 22:30:45 GMT
Raw View
Alex <spammers@sod.off> writes:

|>  I was wondering how safe it is to use an iterator on string after
|>  modifying it.

In general, no.  See 21.3/5 -- almost anything which can even
potentially permit the modification of the string (such as obtaining a
non-const iterator) can invalidate all iterators.

|>  Example:
|>  bool in_string = false;
|>  string::iterator sit = str.begin();
|>  string::iterator first, last;
|>  for(; sit != str.end() ; ++sit) {
|>     if(*sit == '"'){
|>       if(! in_string) {
|>          first = sit;
|>          in_string = true;
|>          continue;
|>       }
|>       else {
|>          last = sit;
|>          in_string = false;
|>          str.replace(first,last,replacement_string);
|>        // is it safe to use sit now?
|>        // if so, where does it point?
|>        // if not, what would be the smart way to do it?
|>      }
|>    }
|>  }

All of the iterators are invalidated by the replace.  Any further use
will result in undefined behavior.

The simplest and safest way of doing this is to create a new string,
rather than doing the modifications in place.

|>  This stupid example illustrates what I want to do. On gcc 2.95.2 I will
|>  get a segfault and/or exception quit soon, but gcc 2.95.2 also typedefs
|>  a string::iterator as char pointer. What does the standard say about
|>  this?

The g++ implementation is conforming.

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

---
[ 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.research.att.com/~austern/csc/faq.html                ]