Question

In my application I have the following record:

TTransaction = record
  Alias: string
  Description: string
  Creation: TDateTime
  Count: Integer
end;

and I'm using this record in this array:

Transactions = array of TTransaction;

I'm keeping the array loaded during runtime, but at a given time I need to clear all data and add some new.

Is it enough just to use:

SetLength(Transactions, 0); ?

Or do I need to finalize something ?

Was it helpful?

Solution

There are three ways to deallocate the memory associates with a dynamic array, a:

SetLength(a, 0);
Finalize(a);
a := nil;

It's up to you which one to use.

The documentation says the same, albeit in a slightly round about fashion:

To deallocate a dynamic array, assign nil to a variable that references the array or pass the variable to Finalize; either of these methods disposes of the array, provided there are no other references to it. Dynamic arrays are automatically released when their reference-count drops to zero. Dynamic arrays of length 0 have the value nil.

This will release all memory associated with the array, including any nested managed types, such as strings, dynamic arrys etc. that are owned by your record type.

If you need to resize the array for future use, and have the new data available, simply resize using SetLength, and initialise the remaining elements appropriately.

OTHER TIPS

Setting the array length to zero will destroy the array, which goes counter to your desire to "keep the array loaded." However, it will free the memory for all the records and their strings (for any strings whose reference count is 1 at the time).

If you just want to free the memory for the strings, but keep the record memory allocated (because you plan to allocate another set of records immediately afterward, and you don't want the waste of releasing and re-allocating the same memory), then you can clear just the string members, but there's no single library call to do it for you. Instead, you'll need to write a loop and clear each record's fields yourself.

for i := 0 to High(transactions) do begin
  transactions[i].alias := '';
  transactions[i].description := '';
end;

If there are lots of fields in the record that need clearing, then it might be more convenient to assign a default TTransaction value to each element of the array. You can use the Default function, or in older versions of Delphi you can declare a TTransaction that has all its fields clear already:

const
  ClearTransaction: TTransaction = (alias: ''; description: ''; creation: 0; count: 0);

for i := 0 to High(transactions) do
  transactions[i] := ClearTransaction;
  // or
  transactions[i] := Default(TTransaction);

SetLength (transactions,0) is not a good idea. I think the best way is to reinitialize all the record's members. This way, you keep the variable loaded.

You can use SetLength (transactions,0) if you don't need the variable anymore, to use as little memory as possible. Of course, if you need it again somewhere in the program, you can re-adjust its length, suppose you know it.

You do not need to finalize anything, beause it's a record, not a class. Records do not have constructors or destructors, like classes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top