Delphi - 结构体中的字符串未被释放 [FastMM 管理器]

4
如果我声明:
PSomeStruct = ^TSomeStruct;
TSomeStruct = record 
  s1 : string;
end;

我运行了以下代码:

var
  p: PSomeStruct;
begin
  new(p);
  p^.s1:= 'something bla bla bla';
  dispose(p);

FastMM 4内存管理器报告发现有内存泄漏(类型:字符串,数据转储:“something bla bla bla”)。然而,在调用dispose之前将s1字符串设置为空,则可以避免该问题。

我找到的第二种方法是将记录类型更改为类,然后不再使用new,而是创建实例,不再使用dispose,而是调用instance.Free()。这样可以避免手动清理字符串。

是否有一种方法可以在调用dispose时让Delphi自动清理我的字符串?

2个回答

1

你已经在做正确的事情了。如果FastMM说字符串泄漏了,那么FastMM是错误的,或者它报告的是与你认为的不同的字符串。Dispose过程会释放记录中的字符串。

在这种特殊情况下,该字符串本来不应该分配任何内存。它是一个字符串字面量,所以我希望编译器会分配该字面量;它的引用计数应该是-1,FastMM永远不应该看到它。


其实,我有点作弊,只是为了让我的想法更清晰。实际上,该字符串是从JvSimpleXML中加载的,但我确信它与报告的字符串相同,因为我进行了检查——在“处理”之前将记录中的所有字符串字段设置为空可以使内存泄漏报告消失... - migajek
1
D7: 我曾经有过一些FastMM报告类似情况的经验——本应该通过记录终结来清理的东西被报告为泄漏。FastMM可能存在这种类型特定的bug看起来很奇怪,我更倾向于怀疑编译器错误,因为一直存在的共同元素都应该由记录终结清理。 - Loren Pechtel
好的,打开“调试DCUs”,并逐步执行Dispose调用。应该会有一个对_FinalizeArray的调用,然后它应该调用_LStrClr。如果这是编译器的错误,那么它一定是在为记录生成TTypeInfo数据时出错了,如果那个数据是错误的,那么New代码也将是错误的。你可能会面临未初始化字符串字段的危险。 - Rob Kennedy

1

FastMM是您的.dpr中使用的第一个单元吗?否则,它可能会过早地完成,报告虚假的内存泄漏。

当您使用JvSimpleXML时,这个简化的代码示例是否也会生成相同的内存泄漏?如果不是,那么可能有更多的事情发生了。

在我看来:当FastMM报告内存泄漏时,就存在内存泄漏。


是的,这是第一个问题。它与JvSimpleXML无关,如果我分配任何字符串(例如来自TEdit.Text的字符串),它也会泄漏内存 :/ - migajek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接