egcs-1.0 memory bug in <string>

Ian Haggard ian@shellus.com
Thu Dec 18 07:47:00 GMT 1997


R. Ebert wrote:
> 
> Depending on the size of your virtual memory the following program
> crashes after 30 to 500 loops.
> 
> int main ()
> {
>   // string -  BUG 3 - Demo
>   string s1 = "a";
>   string s2;
> 
>   for (int i=0; i<70; i++)
>   {
>     s2 = s1;        // now two references to rep
>     s1[1] = 'a';    // s1 gets duplicated via unique()
>     cout << s1.capacity() << endl;  // ... and grows and grows
>   }
> }
> 
> Virtual memory exceeded in `new'
> 
> The problem is in
> 
>   void unique () { if (rep ()->ref > 1) alloc (capacity (), true); }
>                                                ^^^^^^^^

Actually, the problem is not just here, but rather it is also caused by the
interactions between these two functions:

inline basic_string <charT, traits>::Rep * basic_string <charT, traits>::Rep::
create (size_t extra)
{
  extra = frob_size (extra + 1);
  //etc.
}

void basic_string <charT, traits>::
alloc (size_t size, bool save)
{
  if (! check_realloc (size))
    return;

  Rep *p = Rep::create (size);
  // etc.
}

Because create is being called from alloc with extra=capacity() (and capacity
is already a frob_size'd number), adding 1 to extra causes it to be bumped up
to the next frob_size().  Which is the next power of two, of course.

> Thus a more correct implementation might be
> 
>   void unique () { if (rep ()->ref > 1) alloc (length (), true); }

I agree here that passing length() is the best solution.

> 
> or 
> 
>   void unique () { if (rep ()->ref > 1) alloc (capacity () - 1, true); }

I agree that this would work (provided the user is using the default
frob_size() function), but the reason it would work is because it undoes the
extra+1 in the create function.  A bit subtle and difficult to maintain for my
tastes :^)  Also, if the user is not using the default frob_size() function,
and their function is just something like frob_size (size_t s) { return s*5/4;
} or some other space-saving frob_size, then the bug would reappear -- the
"principle" that's being violated here is that no number should be frob_size'd
more than once.
-- 
Ian Haggard  ||  ian@shellus.com (work)  ||  IanHaggard@juno.com (home)
GNU/Linux -- "Oh, no, Mr Bill!" || #define employer_opinion !my_opinion



More information about the Gcc-bugs mailing list