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

跨平台内存泄漏检测工具在Android下的循环引用问题咨询

Great questions—let's tackle each one clearly:

Is this leak caused by circular references?

Absolutely. Your code creates two TMyClassA instances where a.Other = b and b.Other = a. Since Delphi's traditional TObject descendants rely on manual memory management (you call Create but never Free either instance), these two objects will hold references to each other indefinitely. The Delphi memory manager can't automatically detect or resolve this circular dependency—neither object will ever be freed, resulting in the memory leaks you're seeing in logcat.

How to fix the circular reference leak?

You have a few reliable solutions:

  • Explicitly break the circle before freeing
    Use a try/finally block to ensure cleanup, and nullify the cross-references before calling Free:
    procedure TForm1.Button1Click(Sender: TObject);
    var a, b: TMyClassA;
    begin
      a := TMyClassA.Create;
      b := TMyClassA.Create;
      try
        a.Other := b;
        b.Other := a;
        // Perform your intended work here
      finally
        // Break the circular reference first to allow proper cleanup
        a.Other := nil;
        b.Other := nil;
        a.Free;
        b.Free;
      end;
    end;
    
  • Use interfaces with weak references
    Switch to Delphi interfaces (which use automatic reference counting), and mark one of the cross-references as weak to avoid circular reference counting:
    IMyInterface = interface
      ['{YOUR-UNIQUE-GUID-HERE}']
      // Define your interface methods/properties here
    end;
    
    TMyClassA = class(TInterfacedObject, IMyInterface)
    public
      [Weak] Other: IMyInterface; // Weak references don't increment the ref count
    end;
    
    With this setup, when the last strong reference to either object is released, the weak reference won't prevent the object from being destroyed automatically.
  • Implement a custom destructor
    Add an overridden destructor to TMyClassA that clears the Other reference when the object is destroyed:
    type TMyClassA = class(TObject)
    public
      Other : TMyClassA;
      destructor Destroy; override;
    end;
    
    destructor TMyClassA.Destroy;
    begin
      Other := nil; // Break the circular reference chain
      inherited;
    end;
    
    Don't forget to still call Free on both objects (using try/finally is always best practice to guarantee cleanup even if an error occurs).

Why does the tool only show leak addresses instead of class names?

There are three key likely reasons:

  1. Limited RTTI access on Android: The cross-platform leak detector you're using may not be able to access Delphi's Runtime Type Information (RTTI) on the Android platform. Without RTTI, it can't map raw memory addresses back to the corresponding class names.
  2. Tool design constraints: Some lightweight leak detectors only track raw memory allocations (size and address) without integrating deeply with Delphi's object model. They can detect that memory wasn't freed, but can't identify the specific class of the leaked object.
  3. Missing debug symbols: If you're running a release build (or a debug build without full symbol generation enabled), the tool won't have the necessary metadata to resolve memory addresses to class names. Ensure you're using a debug build with symbol generation turned on in your project settings.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:02:33