【问题标题】:Why do I have to cast to a specific pointer type before calling Dispose?为什么在调用 Dispose 之前必须强制转换为特定的指针类型?
【发布时间】:2011-12-16 12:57:51
【问题描述】:

假设我有一个 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() 函数有一个 Pointer 参数,所以在这种情况下强制转换似乎很愚蠢,但我仍然不确定。因为 Dispose() 函数在得到一个通用的 Pointer 类型时如何知道要释放多少内存??

这是第二种方法(没有类型转换):

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

如果有人向我解释应该如何完成以及为什么这样做,我将不胜感激。非常感谢。

【问题讨论】:

    标签: delphi pointers casting dispose


    【解决方案1】:

    是的,必须转换为正确的指针type。没有它,RTL 不知道该记录有一个字符串成员,因此它不会处理该字符串。它会直接跳到释放记录自己的内存,字符串的内容会泄漏。它知道要为记录释放多少内存,就像FreeMem 知道从GetMem 调用中释放多少内存一样。内存管理器知道每个分配有多少内存。 (有多种方法可以跟踪它。)

    Dispose 是一个“编译器魔法”功能。当编译器看到你调用它时,它会为与指针类型对应的TTypeInfo 记录添加一个隐藏的第二个参数。这样,RTL 的Dispose 函数就知道如何处理它接收到的指针。

    【讨论】:

    • 谢谢,@Premature。下次,您可以自行更正此类明显的拼写错误。
    猜你喜欢
    • 1970-01-01
    • 2021-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多