There is another possible pitfall with dynamic arrays I trapped into which I 
would like to share.
Those who handle dynamic arrays in a virtuoso manner daily may skip this 
posting of course.
But I think for those who never used them before it may be of use.
Maybe it can be added to the Wiki (although again I had to make assumptions 
which may be wrong):



With the following declaration and code:

-------------------
var A,B: array of integer;
...
SetLength(A,10);
B := A;
SetLength(B,20);
-------------------

both variables A and B point to the same array with 20 Elements.
Changing A changes B and vice versa.
But a slight modification

-------------------
SetLength(A,0);
B := A;
SetLength(B,20);
-------------------

makes both variables A and B totaly decoupled! Although B is still assigned to 
be the same as A each variable is now a separate array with individual lengths 
and elements. Variable A has the length 0 and variable B is of length 20. 
Changing the length for one of them does no longer change the length of the 
other. If someone thinks about dynamic arrays as black boxes without the need 
to know the details because they are handled in the background then he will 
certainly be baffled by this.

Why is this so? Actually the variables A and B are just (4 byte) pointers to a 
structure which holds further information of the array (reference counter, 
length, pointer to the elements...). Setting the length of such a dynamic array 
to zero means that all data it pointed to will be freed and the pointer is set 
to NIL. Assigning this NIL-value to another variable of the same type sets this 
one to NIL too (after removing any potentially existing data of it). Changes 
for each of these variables no longer affect the other one because they do not 
point to the same structure anymore. Each has its own structure when adding 
elements with SetLength. This is especially a pitfall when the dynamic array is 
part of a complex structure and the reference to it should be given back by 
function or procedure parameters. It will work as long as the array has 
elements but fail when all elements have been (temporarily) removed!

Under the hood dynamic arrays are similar to pointers to records:

-------------------
type MyType = record
              ....
              end;
var A,B : ^MyType;
-------------------

After

-------------------
new(A);
B := A;
-------------------

B points to the same structure as A and changing A^ changed B^ too.
But after

-------------------
dispose(A);
A := nil;
B := A;
-------------------

A and B are both nil and

-------------------
new(A);
new(B);
-------------------

would create two different structures with each variable pointing to one of 
them. The same happens for dynamic arrays. Each length-command changes the 
structure where the pointer points to but when set to length zero it does not 
point to anything anymore (is NIL). Afterwards both variables are independend 
from another.

I think this is an important information about dynamic arrays which I was 
missing from the documentation.
Without this knowledge it can be hard to find subtle errors.


_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to