6 Answers

26
votes

Simple answer No.

Delphi is not a complete garbage collection language, user-defined types should be manually allocated and deallocated. It only provide automatic collection, for a few built-in types, such as strings, dynamic arrays and interfaces for ease of use.

But you can use interfaces which uses reference counting for garbage collection for some extent.

21
votes

Yes, it does.

Delphi Win32 does not include a garbage collector out of the box so the other answers to this question are technically correct. However, this doesn't imply that it isn't possible or that one doesn't already exist. Thanks to Delphi's replaceable memory manager Barry Kelly implemented a fully functional wrapper for the Boehm garbage collector back in 2004.

It includes sample code demonstrating its use (basically creating unassigned objects and watching the GC chew them up). There are more advanced GCs than the Boehm GC but this clearly demonstrates its possible and it can be used almost transparently. You just add the gc unit to the beginning of your project's uses clause.

And while I've not heard of any projects attempting it there is nothing preventing someone from wrapping or porting a more advanced gc.

8
votes

In the usual sense of garbage collection, where the runtime detects unreferenced objects and destroys them or otherwise reclaims unused resources, no, Delphi does not have garbage collection.

If you use native Win32 Delphi, then the closest you have to garbage collection is the various reference-counted types, including strings, interfaces, variants, and dynamic arrays. Those types will get cleaned up automatically when your program determines that they are no longer being used, but it does that by keeping a reference count as those objects enter and leave the current scope. You also have the concept of ownership, which will destroy owned components when the owner is destroyed.

If you use Delphi for .Net, then you implicitly have the garbage collection of the underlying runtime.

2
votes

Delphi-Prism

has Garbage Collection as it is based on .NET

Standard Delphi ( native Win32 )

Does not have Garbage Collection

1
votes

Delphi Win32/64 does not have a garbage collector. You can however take advantage of Delphi native references counting mechanism to have instances released automatically by using interfaces.

The differences between a garbage collector and a reference counting mechanism is that you will have to deal with circular references, i.e. if A and B instances reference each other, you need to manually break the cycle for A or B to be released.

1
votes

Yes! Look at this class

unit uGC;

interface

uses
  System.Generics.Collections, Rtti, System.Classes;

type
  TGarbageCollector = class(TComponent)
  public
    const
      DEFAULT_TAG = 'DEFAULT_TAG';
  private
    items: TDictionary<TObject, string>;
  public
    destructor Destroy; override;
    constructor Create(AOwner: TComponent); override;
    function Add<T>(item: T): T; overload;  
    function Add<T>(item: T; const tag: string): T; overload;  
    procedure Collect(const tag: string);
  end;

var
  GC: TGarbageCollector;

implementation

uses
  System.Types, System.SysUtils;


constructor TGarbageCollector.Create(AOwner: TComponent);
begin
  inherited;
  items := TObjectDictionary<TObject, string>.Create([doOwnsKeys]);
end;

destructor TGarbageCollector.Destroy;
begin
  items.free();
  inherited Destroy;
end;

function TGarbageCollector.Add<T>(item: T): T;
begin
  result := Add(item, DEFAULT_TAG);
end;

function TGarbageCollector.Add<T>(item: T; const tag: string): T;
var
  obj: TObject;
  v: TValue;
begin
  v := TValue.From<T>(item);
  if v.IsObject then
  begin
    items.add(v.AsObject, tag);
    result := item;
  end
  else
    raise Exception.Create('not an Object');
end;

procedure TGarbageCollector.Collect(const tag: string);
var
  key: TObject;
  item: TPair<TObject, string>;
  gcList: TList<TObject>;
begin
  gcList := TList<TObject>.Create();
  try
    for item in items do
    begin
      if (item.Value = tag) then
        gcList.add(item.Key);
    end;

    for key in gcList do
      items.remove(key);
  finally
    gcList.free();
  end;
end;

end.

Create it like this

program GarbageCollector;

uses
  Vcl.Forms,
  uMain in 'uMain.pas' {Main},
  uGC in 'uGC.pas',
  uSomeClass in 'uSomeClass.pas';

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  GC := TGarbageCollector.Create(Application); // <<<
  Application.CreateForm(TMain, Main);
  Application.Run;
end.

Use it like this

  someInstance := GC.Add(TSomeClass.Create(nil), 'TSomeClassTag');
  // do smth with someInstance
  //now destroy
  GC.Collect('TSomeClassTag');
  //
  anotherInstance := GC.Add(TSomeClass.Create(nil), 'TSomeClassTag');
  // do smth with anotherInstance
  // not destroying here - will be destroyed on app destroy...