You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi技术问询:TDemo.TBuilder为何未自动释放引发内存泄漏?

为什么TDemo.TBuilder没有自动释放并导致内存泄漏?

这个问题的核心在于你没让TInterfacedObject的引用计数机制真正生效——虽然TBuilder继承自TInterfacedObject,但只有当对象被赋值给接口类型变量时,Delphi的自动引用计数(ARC)才会启动工作。

问题根源分析

看你的Using方法代码:

class procedure TDemo.Using;
begin
  with TDemo.TBuilder.Create.Generate do
    try
      // 使用TDemo
    finally
      Free;
    end;
end;

这里TDemo.TBuilder.Create确实创建了TBuilder实例,但你直接链式调用了Generate方法,没有把这个实例赋值给任何接口类型变量。

TInterfacedObject的引用计数逻辑是这样的:只有当对象被赋值给接口变量时,才会触发_AddRef增加引用计数;当接口变量离开作用域时,会触发_Release减少计数,计数归0时自动销毁对象。而你现在的写法里,TBuilder实例从创建到调用完Generate,全程没有触发任何引用计数操作,自然没人去释放它,最终造成内存泄漏。

解决方案

要让TBuilder被自动释放,你需要做两件关键的事:

  1. 给TBuilder定义对应的接口类型
    先在TDemo的public区块里声明接口,让TBuilder实现这个接口:

    TDemo = class
    public
      type
        IBuilder = interface
          ['{这里替换成你自己生成的GUID}']
          function Generate: TDemo;
        end;
        TBuilder = class(TInterfacedObject, IBuilder)
        public
          function Generate: TDemo;
        end;
    public
      class procedure Using;
    end;
    
  2. 用接口类型持有TBuilder实例
    修改Using方法,把创建的TBuilder赋值给接口变量,让引用计数机制接管生命周期:

    class procedure TDemo.Using;
    var
      Builder: IBuilder;
      DemoInst: TDemo;
    begin
      Builder := TDemo.TBuilder.Create; // 赋值给接口,触发_AddRef
      DemoInst := Builder.Generate;
      try
        // 使用DemoInst
      finally
        DemoInst.Free;
      end;
      // Builder离开作用域时,自动调用_Release,计数归0后销毁TBuilder
    end;
    

如果想保留链式调用风格,也可以这样写(本质还是借助接口触发计数):

class procedure TDemo.Using;
var
  DemoInst: TDemo;
begin
  DemoInst := (TDemo.TBuilder.Create as IBuilder).Generate;
  try
    // 使用DemoInst
  finally
    DemoInst.Free;
  end;
  // 临时接口引用销毁时,自动触发_Release释放TBuilder
end;

关键要点总结

  • TInterfacedObject只是实现了接口的引用计数逻辑,但必须通过接口类型访问对象,才能激活这个逻辑。
  • 直接用类的Create方法创建实例却不赋值给接口变量,和普通TObject子类没有区别,不会自动释放。
  • 只要对象被接口变量持有,就不需要手动Free,接口离开作用域时会自动完成释放操作。

内容的提问来源于stack exchange,提问作者THSoftPoland

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:48:00