Delphi 动态数组何时被垃圾回收?

Delphi 动态数组何时被垃圾回收?,delphi,Delphi,动态数组是引用计数的,因此编译器会自动释放内存。我的问题是,这种自动释放究竟何时发生?它是立即发生的,还是在包含过程结束时发生的 这里有一个具体的例子 procedure DoStuff; var data:TBytes; begin data:=GetData; // lets say data now contains 1 Gig of data. DoStuffWithData(data); // I now want to free up this 1Gig of memor

动态数组是引用计数的,因此编译器会自动释放内存。我的问题是,这种自动释放究竟何时发生?它是立即发生的,还是在包含过程结束时发生的

这里有一个具体的例子

procedure DoStuff;
var data:TBytes;
begin
  data:=GetData; // lets say data now contains 1 Gig of data.
  DoStuffWithData(data);
  // I now want to free up this 1Gig of memory before continuing.
  // Is this call needed, or would the memory be freed in the next line anyway?
  Finalize(data); 

  data:=GetMoreData; // The first array now has no remaining references
  DoStuffWithData(data);
end

对Finalize()的调用是多余的吗?

Finalize
的调用不是很多余。的确,动态数组的引用计数将在下一行递减(因此可能会销毁该数组),但这只会在分配新的动态数组后发生。在返回
GetMoreData
之前,但在赋值发生之前,内存中将有两个动态数组。如果事先手动销毁第一个阵列,那么一次内存中只能有一个阵列

DoStuff
返回时,存储在
data
中的第二个数组将被销毁(假设
dostufwithdata
未将动态数组引用的副本存储在其他位置,从而增加其引用计数)

这种自动释放究竟何时发生?它是立即发生的,还是在包含过程结束时发生的

当引用计数设置为0时,将释放与托管类型(动态数组属于此类)关联的动态内存。这可能发生在以下几点:

  • 将为参考变量指定一个新值。调用Finalize可以被认为是新值为nil的特例
  • 引用变量超出范围。例如:
    • 到达函数的出口;局部变量超出范围
    • 对象被销毁,其成员超出范围
    • 使用Dispose函数销毁指向记录的指针;记录的所有字段都超出范围
    • 最终确定单位,并最终确定单位中定义的所有全局变量
  • 请注意,上面的各种情况只会在正在完成或正在离开作用域的引用是最后一个剩余引用时导致内存被释放。换句话说,当引用计数为1时

    在您的特定示例中,假设删除了Finalize,您将创建一个新的动态数组,并将其分配给一个已经包含动态数组的变量。这属于上面列表中第1项所述的类别。因此,从这个意义上说,要求最终确定是多余的


    Rob解释了分配和解除分配发生的顺序,这是一个很好的观点。据我所知,这是一个没有明确记录的实现细节。然而,如果这个细节发生了变化,我会感到惊讶。

    为了澄清,在这种情况下,
    data
    的赋值将在
    GetMoreData
    中赋值/
    SetLength
    结果
    时进行。从函数返回的动态类型的工作方式如下:
    GetMoreData(var结果:TBytes)