From: GER.XSE0039@AppleLink.Apple.COM (Germany - C Brinkschulte Berlin,IDV)
Newsgroups: comp.sys.mac.oop.macapp3
Subject: Re:Re: Bug in TDynamicArray
Date: 16 Dec 92 15:46:00 GMT
Organization: AppleLink Gateway

>The problem arises when a TDynamicArray is cloned while an Iterator which was
>used for the TDynamicArray is stil in scope. TDynamicArray has a field named
>fIteratorPtr, which contains a linked list of Iterators currently in use for
>the TDynamicArray. When a TDynamicArray gets cloned, both (the old and the
>cloned Array's) fIteratorPtrs point to the same Iterator. If the
>CArrayIterator
>is destructed, the fIteratorPtr of the cloned TDynamicArray points to an
>invalid Memory-Address.
 
Response:
 
>By golly, you're right!  How they ever let one this obvious slip through
>I'll never know.  TDynamicArray should have a Clone override that sets
>fIteratorPtrs = NULL.
 
>What the heck are you doing that creates a clone of the array while you're
>iterating it?  It seems to me that the only time that linked list of iterators
>get used is when iterations are nested -- unless you are instantiating
>iterators as seperate objects and not by the usual method on the stack.
 
 
*Every* Iterator inserts itself into the linked list of Iterators found inside
TDynamicArray it is attached to. This is necessary, because the Iterators have
to be informed, if an element gets inserted into or deletetd from the Array
while iterating over the Array. They have to be informed, so they can adjust to
the new size of the Array. (A very nice feature, by the way). It is not
necessary to have multiple or nested Iterators to trigger the bug.
 
In fact, it is very easy to run into the problem. The following code is an
example on how _EASY_ it is:
 
TDynamicArray* aDynamicArray = new TDynamicArray;
aDynamicArray->IDynamicArray (0, sizeof (MyStruct));
 
CArrayIterator iter (aDynamicArray);
 
for (   ArrayIndex index = iter.FirstIndex ();
        iter.More ();
        index = iter.NextIndex ())
{
    [do something]
}
 
TDynamicArray* clonedArray = aDynamicArray->Clone ();
 
You dont have to be iterating over the array if you like to run into the
problem. The point is that as long as the Iterator is in scope, (the block the
Iterator was declared), its destructor does _NOT_ get called. So it stays
inside the linked list of Iterators attached to the DynamicArray. This leads to
the conclusion that one never should clone a List or DynamicArray after or
while iterating over the array.
 
Another workaround for this problem is to make a seperate block for the
Iterator so its destructor gets called (which removes itself from the linked
list of Iterators) before cloning the Array:
 
TDynamicArray* aDynamicArray = new TDynamicArray;
aDynamicArray->IDynamicArray (0, sizeof (MyStruct));
 
{   // Extra block to limit the scope of the Iterator
    CArrayIterator iter (aDynamicArray);
 
    for (   ArrayIndex index = iter.FirstIndex ();
            iter.More ();
            index = iter.NextIndex ())
    {
        [do something]
    }
}
 
TDynamicArray* clonedArray = aDynamicArray->Clone ();
 
I think this explains the range of the problem better than my first link.
 
Please send me a copy of any replys, because I am not part of MacAppTech$
anymore (it has flooded my In-Box too much).
 
Carsten Brinkschulte
Berlin
GER.XSE0039