为什么在调用Dispose之前必须将其转换为特定的指针类型?

12

假设我有一个 TList 类的实例(BDS 2006,因此这是指针类型列表)。 我放入列表中的每个指针都引用 New() 函数分配的内存。 因此,当我想要清除列表时,我必须遍历它并释放每个项目,对吗?但是如何正确地执行此操作?我是否需要将每个已释放的项转换为其实际类型?

type
  TMyRec = record
    Field1: string;
    Field2: integer;
  end;
  PMyRec = ^TMyRec;

  ...

  var
    MyList: TList;
    MyRecPointer: PMyRec;
  begin
    ...
    New(MyRecPointer);
    ...
    MyList.Add(MyRecPointer);
    ...

    for i := 0 to MyList.Count - 1 do
      Dispose(PMyRec(MyList[x]));        

    MyList.Clear();
  end;
请看最后的for循环。我将每个项目转换为PMyRec以释放内存。这是必要的吗?我知道Dispose()函数有一个指针参数,所以在这种情况下进行类型转换似乎很愚蠢,但我仍然不确定。因为当Dispose()函数接收到通用指针类型时,它如何知道要释放多少内存?这是另一种没有类型转换的方法:
for i := 0 to MyList.Count - 1 do
  Dispose(MyList[x]);  

如果有人能够向我解释如何做以及为什么要这样做,我将不胜感激。非常感谢。

1个回答

13
是的,必须转换为正确的指针类型。如果不这样做,RTL 就不知道记录是否有字符串成员,因此它不会处理该字符串。它直接跳过释放记录自身内存,并且字符串内容将泄漏。它知道从 GetMem 调用中释放多少内存,同样也知道释放记录所需的内存量。内存管理器知道每个分配的内存量(有多种跟踪方式)。 Dispose 是一个“编译器魔法”函数。当编译器看到您调用它时,它会为指针类型对应的 TTypeInfo 记录添加隐藏的第二个参数。这样,RTL 的 Dispose 函数就知道如何处理它接收到的指针。

谢谢,@Premature。下次如果有明显的错别字,请随意自行更正。 - Rob Kennedy

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