2
procedure FreeListObjects( l : TStrings);
var i : integer;
BEGIN
   FOR i :=  0 TO l.Count -1 DO BEGIN
       l.Objects[i].Free;
       l.Objects[i] := NIL;
   END;
end;



PROCEDURE StringListAdd;
VAR i : INTEGER; Code : LONGWORD;
BEGIN
   l := Classes.TstringLIST.CREATE;
   FOR i := 0 TO 4 DO BEGIN
       Code := i  ;
       l.AddObject('', TObject(code));
   END;
   Code := LONGWORD(l.Objects[2]);
   FreeListObjects(l);
   l.Free;
END;

当我不使用l.OwnsObjects := TRUE FreeListObjects(l),会发生错误。

谁来释放这个字符串列表的对象?

4

7 回答 7

7

您已经告诉字符串列表它拥有其Objects数组中的对象。在这种情况下,它会在您销毁列表时自动调用Free所有这些值,就像您的FreeListObjects代码一样。

但是那里没有物体!您已经获取了Integer不是对象的值,并将它们强制转换为TObject. 您不能调用Freean Integer,但在任何代码调用Free时,它都不知道值的原始类型。当您进行类型转换时,您告诉编译器您知道自己在做什么,并且编译器相信您。如果您真的不知道自己在做什么,请不要进行类型转换。

你说你会得到错误FreeListObjects,但你也应该得到 错误FreeListObjects。问题是您正在调用Free不是对象的东西。无论您是在自己的代码中调用它还是让库调用它都无关紧要。

您可能已经花了一些时间使用 C#。在那种语言中,整数会自动“装箱”成为真实的对象。这不是 Win32 Delphi 的工作方式。Delphi 不做装箱和拆箱。

于 2009-09-08T14:01:34.353 回答
3

OwnsObjects 与您的 FreeObjects 例程基本相同,但它在 StringList 本身被释放时在内部处理它。

但在我看来,您的问题来自您的示例。当我运行它时,我会遇到访问冲突,因为您保存的“对象”根本不是对象,它们是您强制到 TObject 插槽的整数。

这只是一个猜测,但是您是否只是在学习“一切都是对象”的其他语言背景之后才学习 Delphi?在德尔福中并非如此。对象是众多数据类型中的一种,您不能在其他数据类型上调用 Free。

于 2009-09-08T14:02:24.207 回答
3

问题在于,当您设置 OwnObjects := true 时,列表将免费调用其中的每个项目。但是,由于您只是将整数转换为 TObject 并且您并没有真正创建 Integer 类型的对象,因此您无法调用此转换对象中的任何方法。

解决您的问题的方法是创建一个这样的类:

TInteger = class
  value: integer;
  constructor Create(v: integer);
end;

并将您的列表项放入此类的实例中,替换:

   l.AddObject('', TObject(code));

   l.AddObject('', TInteger.Create(code));
于 2009-09-08T14:10:00.210 回答
2

扩展 Rob 的答案:您试图释放与地址相关的东西:分别为 nil、0x00000001、0x00000002、0x00000003 和 0x00000004。由于那里没有有效的对象,因此会出现访问冲突(注意:在 nil 对象上调用 Free 不会产生错误)。

于 2009-09-08T14:05:25.847 回答
0

我知道在 Delphi 中,您需要通过执行以下操作来释放每个对象。

例如,如果您的对象属于以下类别。

TheClass = Class(TObject)
public
thestr:String;
end;

然后你会这样做:

procedure FreeListObjects( l : TStrings);
var i : integer;
BEGIN
   FOR i :=  0 TO l.Count -1 DO BEGIN
       TheClass(l.Objects[i]).Free;   <----
       l.Objects[i] := NIL;
   END;
end;

TStrings 列表中的每个对象实际上都驻留在它们自己的内存位置,即使您正在释放指向对象的指针。您需要通过执行上述操作来释放对象内存。我就是这样做的,并且在 Delphi 中做到了。它一直对我有用。

于 2011-09-06T13:11:11.383 回答
0

其他人已经在您的代码中指出了问题,所以我只添加一个信息。如果您只想将整数存储在列表中,请使用我的GpLists单元中的 TGpIntegerList 或 TGpInt64List。免费,没有附加条件。

于 2009-09-09T08:14:17.967 回答
0

抱歉,这是我第一次在 stackoverflow 中,下次我的问题会更准确。我认为 l.addobject 将在 tstringlist 中创建和添加对象。l.addobject('', tobject(code)) (其中 l 是 tstringlist 而代码是长字)是否会造成内存泄漏?longword 什么时候定位?我总能得到代码 := Longword(L.objects[i]); 我正在输入什么对象?

于 2009-09-09T12:35:05.660 回答