2

FastMM 报告以下代码片段的内存泄漏 (UnicodeString),该代码片段使用带有字符串的记录线程变量:

program Project10;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  FastMM4,
  System.SysUtils;

type
  TContext = record
    Value : String;
  end;

threadvar
  Context : TContext;

begin
Context.Value := 'asdfsdfasfdsa';
end.

这是真正的内存泄漏,还是在 FastMM 检查内存泄漏后才清理线程变量?

更重要的是:我如何才能抑制报告这些“内存泄漏”,因为它们会混淆可能发现的任何其他内存泄漏?

4

2 回答 2

6

这是一个真正的泄漏。线程局部变量超出范围时未最终确定。由于您的记录包含一个托管字段,即字符串字段,因此如果记录未最终确定,则与该字符串关联的堆分配内存会泄漏。

文档明确指出了这一点:

通常由编译器管理的动态变量(长字符串、宽字符串、动态数组、变体和接口)可以用 threadvar 声明,但编译器不会自动释放每个执行线程创建的堆分配内存。如果您在线程变量中使用这些数据类型,您有责任在线程终止之前从线程内处理它们的内存。

如果你想堵塞泄漏,你需要在作用域结束时完成变量。也就是说,因为线程正在终止。

Finalize(Context);

请注意,您必须从拥有该变量的线程执行此代码,因为显然只有该线程可以访问它。

如果您想禁止报告这些泄漏,请调用 RegisterExpectedMemoryLeak。

如果在线程终止时无法执行代码,那么最好避免堆分配并使用固定长度的字符数组。很可能满足您的需求。

当线程终止时,您声称无法执行代码似乎很奇怪。如果你不能这样做,你怎么能在这些线程的上下文中执行任何代码。换句话说,为了发生泄漏,您必须已经在这些线程中执行了您的代码。

于 2013-08-22T08:37:12.020 回答
0

创建 TContext 的全局数组,然后将属于您的线程的元素的索引存储在 threadvar 中。

于 2013-08-22T11:24:14.470 回答