Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Dynamic Array need cleaning up?

621 views
Skip to first unread message

Vagn Kristensen

unread,
Jul 14, 2002, 8:38:45 AM7/14/02
to
Hello.

I've got a procedure that builds a somewhat big dynamic array of
objects. I've noticed that each time I call this procedure, the program
uses more and more memory, so I've come to the conclusion that I'm not
"cleaning up" after myself.

I would have thought that the array would be destroyed and memory freed
when the procedure exists. So could anyone enlighten me on how I should
free the memory that my array occupies. Do I need to run through all the
elements and setting it to free(?) or can it just SetLength(array, 0).

Anyone?

David Reeve

unread,
Jul 14, 2002, 9:59:43 AM7/14/02
to

Vagn Kristensen <vagn...@hotmail.com> wrote in message
news:MPG.179b8f3c9...@news.tiscali.dk...

> free the memory that my array occupies. Do I need to run through all the
> elements and setting it to free(?)

yes


Rudy Velthuis

unread,
Jul 14, 2002, 10:10:56 AM7/14/02
to
On Sun, 14 Jul 2002 14:38:45 +0200, Vagn Kristensen
<vagn...@hotmail.com> wrote:

> I would have thought that the array would be destroyed and memory freed
> when the procedure exists.

It is, but what you store in the array are only pointers, since object
variables are (unlike records) only pointers to the data. The array
containing the pointers is automatically managed, but not the objects
to which these pointers point. So you'll have to free the single
objects one by one.

> So could anyone enlighten me on how I should
> free the memory that my array occupies. Do I need to run through all the
> elements and setting it to free(?) or can it just SetLength(array, 0).

You don't *set* something to free, you call the Free method of each
object. There is usually no need to use

SetLength(thearray, 0);

or

thearray := nil; // does the same as the above

Steven

unread,
Jul 14, 2002, 11:31:15 AM7/14/02
to

"Rudy Velthuis" <rvel...@gmx.de> wrote in message
news:6c13ju4er6g0nublm...@4ax.com...

and if you really want to make it nil, there's always FreeAndNil (well, not
really always; IIRC it was added in D3):
FreeAndNil(thearray);


Rudy Velthuis

unread,
Jul 14, 2002, 12:43:46 PM7/14/02
to
Steven wrote:

> and if you really want to make it nil, there's always FreeAndNil (well,
not
> really always; IIRC it was added in D3):
> FreeAndNil(thearray);

FreeAndNil is only meant to be used for class instances, not for dynamic
arrays. Using FreeAndNil here could have catastrophic consequences. <g>

Steven

unread,
Jul 14, 2002, 3:00:25 PM7/14/02
to

"Rudy Velthuis" <rvel...@gmx.de> wrote in message
news:ags9o2$gh2$07$1...@news.t-online.com...

You're right. I guess you confused me by mentioning the Free method in the
other post. |-)


VBDis

unread,
Jul 16, 2002, 3:18:55 PM7/16/02
to
Im Artikel <7PgY8.5196$8o4...@afrodite.telenet-ops.be>, "Steven"
<stev...@pandora.be> schreibt:

>and if you really want to make it nil, there's always FreeAndNil (well, not
>really always; IIRC it was added in D3):

(AFAIK in D5 ;-)

> FreeAndNil(thearray);

I don't recommend that with dynamic arrays - it should not work at all, because
no Free method exists for dynamic arrays. You are asking for trouble, when
Delphi tries to call an not-existing destructor for a non-object :-(

The FreeAndNil procedure is a dirty hack, which can only work when the argument
really is an object (of some class).


Setting an dynamic array (reference!) to nil can fail to erase the array, when
a reference to the same array exists somewhere else in the program. Remember
that dynamic arrays are reference counted!

IMO the only correct code for erasing an dynamic array is:
SetLength(thearray, 0);

DoDi

David Reeve

unread,
Jul 16, 2002, 9:36:09 PM7/16/02
to

VBDis <vb...@aol.com> wrote in message
news:20020716151855...@mb-mg.aol.com...

> Im Artikel <7PgY8.5196$8o4...@afrodite.telenet-ops.be>, "Steven"
> <stev...@pandora.be> schreibt:
>
>
> IMO the only correct code for erasing an dynamic array is:
> SetLength(thearray, 0);
>

I just checked this on D4 and watched what was happening on MemProof

var
myArray, mySecondArray: array of integer;

SetLength(myArray,100000); // approx 400K allocated
myArray := nil; // approx 400K deallocated

OK .....that's as we'd expect... as is

SetLength(myArray,100000); // approx 400K allocated
mySecondArray := myArray;
myArray := nil; // no deallocation

AND..........

SetLength(myArray,100000); // approx 400K allocated
SetLength(myArray, 0); // approx 400K deallocated

so is this OK......... nice and efficient.......BUT

SetLength(myArray,100000); // approx 400K allocated
mySecondArray := myArray;
SetLength(myArray, 0); // no deallocation

the length change doesn't cause a deallocation while the reference count > 1

FURTHERMORE........

SetLength(myArray,100000); // approx 400K allocated
mySecondArray := myArray; // no change
SetLength(myArray,100000); // another approx 400K allocated
mySecondArray := myArray; // approx 400K deallocated

but what is this one all about?? Somewhere in help I seem to remember
reading SetLength guarantees a unique instance for strings. Perhaps that is
what is happening here, and when you make the second reference, the now
redundant second instance is deallocated.


Dave

AlanGLLoyd

unread,
Jul 17, 2002, 1:43:32 AM7/17/02
to
In article <QD3Z8.3319$Cq.1...@ozemail.com.au>, "David Reeve"
<drscie...@powerup.com.au> writes:

>SetLength(myArray,100000); // approx 400K allocated
>mySecondArray := myArray; // no change
>SetLength(myArray,100000); // another approx 400K allocated
>mySecondArray := myArray; // approx 400K deallocated
>

I would think ...

SetLength(myArray,100000); // approx 400K allocated
mySecondArray := myArray; // no change

... because both reference the same array ...

SetLength(myArray,100000); // another approx 400K allocated

... SetLength guarantees a separate instance so a fresh allocation ...

mySecondArray := myArray; // approx 400K deallocated

... now these _are_ the same so both reference the same memory, and the
previous allocation for MySecondArray (actually the first allocation for
MyArray but transferred to MySecondArray on the second SetLength on MyArray) is
unnecessary.

SetLength guarantees a separate instance _only at that point in time_, not for
any future action. If you re-state the identity then that overcomes the
previous guarantee. Delphi is not yet capable of acting on what you may do in
the future <g>.

Alan Lloyd
alang...@aol.com

Rudy Velthuis

unread,
Jul 17, 2002, 2:51:25 PM7/17/02
to
On Wed, 17 Jul 2002 11:36:09 +1000, "David Reeve"
<drscie...@powerup.com.au> wrote:

> SetLength(myArray,100000); // approx 400K allocated

refcount = 1

> mySecondArray := myArray;

refcount = 2

> SetLength(myArray, 0); // no deallocation

refcount decremented to 1 again



> the length change doesn't cause a deallocation while the reference count > 1
>
> FURTHERMORE........
>
> SetLength(myArray,100000); // approx 400K allocated

refcount = 1

> mySecondArray := myArray; // no change

refcount = 2

> SetLength(myArray,100000); // another approx 400K allocated

refcount of original array decremented to 1 again
new array allocated and assigned to myArray. recount also 1

> mySecondArray := myArray; // approx 400K deallocated

refcount of original array decremented to 0 -> freed
refcount of newer array incremented to 2

VBDis

unread,
Jul 17, 2002, 8:55:00 PM7/17/02
to
Im Artikel <20020717014332...@mb-co.aol.com>, alang...@aol.com
(AlanGLLoyd) schreibt:

>SetLength(myArray,100000); // another approx 400K allocated
>
>... SetLength guarantees a separate instance so a fresh allocation ...

AFAIR it becomes tricky with "var" parameters. When a dynamic array is passed
as a "var" parameter to a subroutine, then the subroutine can modify and
redimension the array at will, and all operations act on the same array. This
is because then not an array reference is passed to the called subroutine, but
instead a reference to the variable which the caller supplied.

Dave wrote:
>mySecondArray := myArray;


>SetLength(myArray, 0); // no deallocation

>the length change doesn't cause a deallocation while the reference count > 1

This is correct. I think that I had in mind the above procedure, where I passed
an array as a "var" parameter, in which case the reference count of the array
is unchanged.

DoDi

David Reeve

unread,
Jul 18, 2002, 4:35:06 AM7/18/02
to

VBDis <vb...@aol.com> wrote in message
news:20020717205500...@mb-mg.aol.com...

> Im Artikel <20020717014332...@mb-co.aol.com>,
alang...@aol.com
> (AlanGLLoyd) schreibt:
>
> >SetLength(myArray,100000); // another approx 400K allocated
> >
> >... SetLength guarantees a separate instance so a fresh allocation ...
>
> AFAIR it becomes tricky with "var" parameters. When a dynamic array is
passed
> as a "var" parameter to a subroutine, then the subroutine can modify and
> redimension the array at will, and all operations act on the same array.
This
> is because then not an array reference is passed to the called subroutine,
but
> instead a reference to the variable which the caller supplied.
>

Now that's a point I have never considered, yet I do this a lot....:-) I
guess an explicit assigment is necessary. If passing by var increased the
reference count, imagine what would happen if you latter sought to add stuff
to the original array and it spawned a new instance!!

Dave


David Reeve

unread,
Jul 18, 2002, 4:36:56 AM7/18/02
to

Rudy Velthuis <rvel...@gmx.de> wrote in message
news:6uebjuoidqi4sd4ar...@4ax.com...

Yes that makes sense

Dave


0 new messages