【问题标题】:Garbage Collection in DelphiDelphi 中的垃圾收集
【发布时间】:2010-12-14 15:36:28
【问题描述】:

德尔福有Garbage Collection吗?

【问题讨论】:

    标签: delphi garbage-collection


    【解决方案1】:

    简单的答案。

    Delphi 不是一个完整的垃圾回收语言,用户定义的类型应该手动分配和释放。它只提供了自动收集,对于一些内置类型,例如字符串、动态数组和接口,以便于使用。

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

    【讨论】:

    • 另外值得一提的是,从 TComponent 派生的任何东西都通过构造函数获取所有者指针,这会导致对象与其所有者一起被销毁。
    • delphi 垃圾收集一些数据类型,如动态数组、字符串。
    • Delphi 熟悉 ARC(自动引用计数),一种管理接口生命周期的方法(实现 RefCount)和其他类型。如今,最新的 Delphi 移动编译器已将 ARC 引入对象。它由编译器指令“{$AUTOREFCOUNT}”控制。见以下链接:docwiki.embarcadero.com/RADStudio/Tokyo/en/…
    【解决方案2】:

    是的,确实如此。

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

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

    虽然我没有听说过任何尝试它的项目,但没有什么能阻止有人封装或移植更高级的 gc。

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

      • Delphi.NET 死了 2 年多了
      • 是的,@User,因为 Delphi 7 已经有十年历史了,它也一定已经死了。此外,Delphi 语言仍可通过 Prism 用于 .Net。
      • Prism 甚至没有尝试共享源,所以我不完全认为这是一个延续。商标除外。
      • Kylix(作为 Linux RTL 和 CLX),Delphi.NET(主观:与 2007 年一样半生不熟)-已停产Delphi 7(实际上不到十年)- EoL,但有活跃的继任者。看到不同? Delphi Schism 是完全不同的产品。那么,近期应该选择什么样的环境,避免被锁在里面呢?
      【解决方案4】:

      德尔福棱镜

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

      标准 Delphi(本机 Win32)

      没有垃圾收集

      【讨论】:

        【解决方案5】:

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

        垃圾收集器和引用计数机制的区别在于你必须处理循环引用,即如果 A 和 B 实例相互引用,你需要手动打破循环以释放 A 或 B。

        【讨论】:

          【解决方案6】:

          是的!看看这堂课

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-01-21
            • 1970-01-01
            • 2018-12-30
            • 1970-01-01
            • 2011-02-25
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多