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检查内存泄漏后才发生线程变量的清理?
更重要的是:我怎样才能抑制这些“内存泄漏”,因为它们会混淆可能发现的任何其他内存泄漏?
答案 0 :(得分:7)
这是一个真正的泄漏。线程局部变量超出范围时不会最终确定。因为您的记录包含托管的字段,字符串字段,如果记录未完成,则与该字符串关联的堆分配内存将被泄露。
documentation明确表示这一点:
通常由。管理的动态变量 编译器(长字符串,宽字符串,动态数组,变体, 和接口)可以用threadvar声明,但编译器不会自动释放堆分配 每个执行线程创建的内存。如果你使用 这些数据类型在线程变量中,这是你的责任 之前从线程中处理内存 线程终止。
如果要插入泄漏,则需要在范围结束时最终确定变量。也就是说,因为线程正在终止。
Finalize(Context);
请注意,您必须从拥有该变量的线程中执行此代码,因为显然只有该线程可以访问该变量。
如果要禁止报告这些泄漏,请调用RegisterExpectedMemoryLeak。
如果在线程终止时无法执行代码,那么最好避免堆分配并使用固定长度的字符数组。很可能你满足了你的需求。
当线程终止时,你声称不能执行代码似乎很奇怪。如果你不能这样做,你如何能够在这些线程的上下文中执行任何代码。换句话说,为了发生泄漏,您必须在这些线程中执行您的代码。
答案 1 :(得分:0)
创建TContext的全局数组,然后在threadvar中存储属于您的线程的元素的索引。