【问题标题】:Memory leak detection and cycles内存泄漏检测和循环
【发布时间】:2018-05-25 19:22:44
【问题描述】:

我尝试使用来自https://bitbucket.org/shadow_cs/ 的跨平台内存泄漏检测代码。

我编写了一个包含循环的小型 Android 演示应用:

type
  TMyClassA = class(TObject)
  public
    Other : TMyClassA;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  a, b: TMyClassA;
begin
  a := TMyClassA.Create;
  b := TMyClassA.Create;

  a.Other := b;
  b.Other := a;
end;

然后我在 Android 上运行它(将所需的单元添加到项目、库路径等)。

当我按下按钮并退出应用程序时,我可以看到大量关于 logcat 中泄漏的消息,但它似乎永远不会结束。

这是因为我的周期吗?

如果是,我需要做什么,为什么它不显示泄漏对象的名称而只显示它们的地址?

摘自logcat:

05-25 21:00:14.257:W/泄漏(8382):检测到泄漏 CC4BC740 尺寸 48 B 05-25 21:00:14.266:W/泄漏(8382):01 00 00 00 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 | ????????????????????????????????? 05-25 21:00:14.302:W/泄漏(8382):00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ??????????????? 05-25 21:00:14.334:W/泄漏(8382):检测到泄漏 CC4BCEC0 尺寸 48 B 05-25 21:00:14.366:W/泄漏(8382):01 00 00 00 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 ????????????????????????????????? 05-25 21:00:14.400:W/泄漏(8382):00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ??????????????? 05-25 21:00:14.425:W/泄漏(8382):检测到泄漏 CC4B1E40 尺寸 256 B 05-25 21:00:14.467:W/泄漏(8382):40 AD 6B CA C0 0F 4C CC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | @?k???L???????????????????????? 05-25 21:00:14.503:W/泄漏(8382):00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 48 12 4C CC 00 00 00 00 | ????????????????????????H?L?????? 05-25 21:00:14.543:W/泄漏(8382):00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 48 1C 4C CC C8 14 4C CC 00 00 00 00 00 00 00 00 | ???????????????H?L???L????????? 05-25 21:00:14.573:W/泄漏(8382):00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 | ????????????????????????????????? 05-25 21:00:14.605:W/泄漏(8382):00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 | ????????????????????????????????? 05-25 21:00:14.639:W/泄漏(8382):00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 | ????????????????????????????????? 05-25 21:00:14.674:W/泄漏(8382):00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 | ????????????????????????????????? 05-25 21:00:14.708:W/泄漏(8382):00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 | ?????????????????????????????????

泄漏检测项目托管在 Bitbucket 上。我是那个新手,但与 GitHub 不同,我看不到任何联系作者的方式。否则我会先问他们。

【问题讨论】:

  • 运行时不存在变量名,所以泄漏日志只能报告地址。您应该在创建对象时记录它们的地址,以便知道哪个泄漏对应于哪个对象名称。从您的日志中可以清楚地看出,您的示例创建的不仅仅是 2 个泄漏。
  • 首先感谢 Remy 的编辑和您的评论。关于广告
  • 关于地址:我习惯于 Win32 上的 FastMM4 泄漏报告,它确实告诉我泄漏对象的类名,所以我的问题有点错误:我不是说变量名,但类名。另一个问题:如果我的项目泄漏的实例多于我的代码摘录显示的这 2 个实例,那么 FMX 应用程序有一些严重的问题。我刚刚创建了一个空白的多设备应用程序,添加了我在问题中显示的按钮和我在问题中显示的代码。仅此而已。
  • 我现在在这里询问了另一个问题:stackoverflow.com/questions/50544275/…
  • @DalijaPrasnikar 我知道你可以把任何东西放在那里,但我知道这里有问题的东西会到达 LeakCheck 的作者 :)

标签: android delphi memory-leaks delphi-10.1-berlin


【解决方案1】:

是的,这是由于周期。为了防止这些泄漏,您必须手动取消分配它们或使用[Weak] 属性,以便编译器/RTL 知道可能的循环,并且在分配给弱字段时引用计数不会增加,而是“记住”分配和取消分配释放对象时的字段(因此您不会访问已释放的实例,但当您进入该场景时仍会获得零指针 AV)。另一种选择是使用[Unsafe](或将您的实例分配/取消分配为Pointer(fField) := instance),它完全禁止ARC和弱引用。

LeakCheck 报告所有内存泄漏,但只有某些类型包含附加信息,因此可以推断类型(LeakCheck 支持字符串/对象),因此您可以忽略这些未知数。

LeakCheck 确实实现了循环检测并以 Graphviz DOT 格式输出,以便可视化。我建议使用文件日志记录(在LeakCheck 之后将LeakCheck.Report.FileLog 添加到您的项目中)它会将泄漏和图形输出到单独的文件(请记住目标文件夹/storage/emulated/0/ 需要由应用程序访问)所以它比 logcat 输出更容易传输处理。有关详细信息,请参阅CustomLeakReportFMX 示例。

【讨论】:

    猜你喜欢
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 2011-12-13
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多