Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When exactly does a dynamic array get garbage collected?

Tags:

delphi

Dynamic arrays are reference counted, and so the memory is freed automatically by the compiler. My question is, when exactly does this automatic freeing occur? Does it happen immediately, or at the end of the containing procedure?

Here is a concrete example

procedure DoStuff;
var data:TBytes;
begin
  data:=GetData; // lets say data now contains 1 Gig of data.
  DoStuffWithData(data);
  // I now want to free up this 1Gig of memory before continuing.
  // Is this call needed, or would the memory be freed in the next line anyway?
  Finalize(data); 

  data:=GetMoreData; // The first array now has no remaining references
  DoStuffWithData(data);
end

Is the call to Finalize() redundant?

like image 479
awmross Avatar asked Nov 08 '11 05:11

awmross


People also ask

How does a garbage collector work?

A garbage collection has the following phases: A marking phase that finds and creates a list of all live objects. A relocating phase that updates the references to the objects that will be compacted. A compacting phase that reclaims the space occupied by the dead objects and compacts the surviving objects.

How does garbage collector know which objects to free?

The truth is that the garbage collector does not, in general, quickly know which objects no longer have any incoming references. And, in fact, an object can be garbage even when there are incoming references it. The garbage collector uses a traversal of the object graph to find the objects that are reachable.

Where does the dynamic array is stored?

The elements of the dynamic array are stored contiguously at the start of the underlying array, and the remaining positions towards the end of the underlying array are reserved, or unused.

How does Javascript garbage collection work?

The garbage collector takes roots and “marks” (remembers) them. Then it visits and “marks” all references from them. Then it visits marked objects and marks their references. All visited objects are remembered, so as not to visit the same object twice in the future.


2 Answers

The call to Finalize isn't quite redundant. It's true that the dynamic array's reference count will be decremented on the next line (therefore destroying the array, probably), but that will only happen after the new dynamic array is allocated. Just before the return of GetMoreData, but before the assignment takes place, there will be two dynamic arrays in memory. If you destroy the first one manually in advance, then you'll only have one array in memory at a time.

The second array that you store in data will get destroyed as DoStuff returns (assuming DoStuffWithData doesn't store a copy of the dynamic-array reference elsewhere, increasing its reference count).

like image 106
Rob Kennedy Avatar answered Oct 12 '22 22:10

Rob Kennedy


When exactly does this automatic freeing occur? Does it happen immediately, or at the end of the containing procedure?

Dynamic memory associated with managed types (dynamic arrays fall into this class) is freed when the reference count is set to 0. This can happen at the following points:

  1. The reference variable is assigned a new value. A call to Finalize can be thought of as the special case where the new values is nil.
  2. The reference variable goes out of scope. For example:
    • The exit of a function is reached; local variables go out of scope.
    • An object is destroyed and its members go out of scope.
    • A pointer to a record is destroyed with the Dispose function; all fields of the record go out of scope.
    • A unit is finalized and all global variables defined in the unit are finalized.

Note that the various cases above only result in memory being freed when the reference that is being finalized or is leaving scope is the last remaining reference. In other words, when the reference count is 1.

In your specific example, assuming the Finalize is removed, you are creating a new dynamic array and assigning it to a variable that already holds a dynamic array. This then falls into the class described by item 1 in the list above. So in that sense the call to Finalize is superfluous.

Rob has explained the order in which the allocation and deallocation happens which is a good point. To the best of my knowledge that is an implementation detail that is not explicitly documented. However, I'd be astounded if that detail was ever changed.

like image 42
David Heffernan Avatar answered Oct 13 '22 00:10

David Heffernan