Delphi中的垃圾收集

时间:2010-12-14 15:36:29

标签: delphi garbage-collection

Delphi有Garbage Collection吗?

6 个答案:

答案 0 :(得分:24)

简单回答否。

Delphi不是一种完整的垃圾收集语言,应手动分配和取消分配用户定义的类型。它仅为少数内置类型提供自动收集,例如字符串,动态数组和界面,以便于使用。

但是你可以在某种程度上使用使用引用计数进行垃圾收集的接口。

答案 1 :(得分:19)

是的,确实如此。

Delphi Win32不包含垃圾收集器开箱即用,因此这个问题的其他答案在技术上是正确的。但是,这并不意味着它不可能或者不存在。感谢Delphi的可替换内存管理器Barry Kelly在2004年为wrapper实现了功能齐全的Boehm garbage collector

它包含演示其使用的示例代码(基本上创建未分配的对象并观看GC咀嚼它们)。有比Boehm GC更先进的GC,但这清楚地证明了它的可能性,它几乎可以透明地使用。您只需将gc单元添加到项目的uses子句的开头。

虽然我没有听说有任何项目尝试过,但没有任何东西阻止某人包装或移植更高级的gc。

答案 2 :(得分:7)

在通常意义上的垃圾收集中,运行时检测到未引用的对象并销毁它们或以其他方式回收未使用的资源,不,Delphi没有垃圾收集。

如果您使用本机Win32 Delphi,则最接近垃圾收集的是各种引用计数类型,包括字符串,接口,变体和动态数组。当程序确定它们不再被使用时,这些类型将自动清理,但它通过保持引用计数,因为这些对象进入和离开当前范围。您还拥有所有权的概念,当所有者被销毁时,它将销毁所拥有的组件。

如果你使用Delphi for .Net,那么你隐式拥有底层运行时的垃圾收集。

答案 3 :(得分:2)

Delphi-Prism

具有垃圾收集,因为它基于.NET

标准Delphi (原生Win32)

没有垃圾收集

答案 4 :(得分:1)

Delphi Win32 / 64没有垃圾收集器。 但是,您可以利用Delphi本机引用计数机制通过使用接口自动释放实例。

垃圾收集器和引用计数机制之间的区别在于您必须处理循环引用,即如果A和B实例相互引用,则需要手动中断A或B的循环。

答案 5 :(得分:0)

是的!看这个课

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.

像这样创建它

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.

像这样使用它

  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...