delphi - GetMem x ReallocMem

标签 delphi arrays memory-management

System.GetMem 和 System.ReallocMem 有什么区别?

Delphi 2009 帮助中对 ReallocMem 的描述与 GetMem 的描述完全相同。 System.FreeMem 和 System.Dispose 怎么样

数组应该使用什么?

type
  PMemberDataList = ^TMemberDataList;
  TMemberDataList = array[0..MaxClassMembers -1] of PMemberData;

var
  FItems: PMemberDataList;

begin
  GetMem(FItems, Value * SizeOf(Pointer));
  FreeMem(FItems);
end;

begin
  ReallocMem(FItems, Value * SizeOf(Pointer));
  Dispose(FItems);
end;

解决方案

根据人们的建议,我将 FItems 声明为记录类型,而不是指向记录的指针,将 TMemberDataList 声明为动态数组,将 SetLength 声明为(解除)分配数组,将 New/Dispose 声明为数据

type
  PMemberDataList = ^TMemberDataList;
  TMemberDataList = array of PMemberData;
var
  Items: TMemberDataList;
  Item: PMemberData;

// Add
begin
  Setlength(Items, 1);
  New(Item);
  Items[0]:= Item
end;

// Remove
begin
  Dispose(Items[0]);
  Setlength(Items, 0);
end;

最佳答案

GetMem 始终分配内存,FreeMem 始终释放/释放内存,ReallocMem 可能会执行其中一项或两项,或两者兼而有之。事实上,如果使用得当,ReAllocMem 实际上是唯一需要的内存管理 API。如果您从 nil 指针开始,并以大小 > 0 调用 ReAllocMem,那么它的作用类似于 GetMem。如果您以 size = 0 调用 ReAllocMem,那么它的作用类似于 FreeMem。它真正“重新分配”内存的唯一时间是指针非零且大小 > 0 时。

New 和 Dispose 旨在与类型化指针一起使用,或者对于“old-skool”人员来说,旧的 Turbo Pascal 对象模型(旧的“对象”)语法。New 和 Dispose 还将确保任何类型化指针对托管类型的引用将正确初始化该类型。例如,给出以下内容:

type
  PMyRec = ^TMyRec;
  TMyRec = record
    Name: string;
    Value: Variant;
  end;

var
  Rec: PMyRec;
begin
  New(Rec);
  try
    Rec.Name := 'TestValue';
    Rec.Value := 100;
    ...
  finally
    Dispose(Rec);
  end;
end;

New 和 Dispose 将确保记录的 Name 和 Value 字段正确初始化、最终确定或清理。 New和Dispose,在上面的情况下相当于:

GetMem(Rec, SizeOf(Rec^));
Initialize(Rec);
...
Finalize(Rec);
FreeMem(Rec);

对于您给出的示例,Gamecat 是正确的,您可能最好使用动态数组,因为它们可以更好地由编译器管理,并且它们还具有自己的固有长度。在您的示例中,您必须单独跟踪数组中的项目数,这样无论您在数组中传递什么位置,您还必须传递当前分配的长度。通过使用动态数组,所有信息都整齐地打包在一起。这将允许您通过简单地执行以下操作之一来迭代数组,而不管当前长度如何:

var
  Member: TMemberData;
  Items: array of TMemberData;
  ...
begin
  SetLength(Items, Value);
  for Member in Items do  // iterate over each element in the array
  ...
  for Low(Items) to High(Items) do // same as above only using std functions
  ...
end;

最后,您可能想要使用动态数组的另一个原因是,如果 TMemberData 包含字符串、变体、接口(interface)或其他“托管”类型,它们将被正确初始化和最终确定,而无需手动执行此操作。

关于delphi - GetMem x ReallocMem,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/569995/

相关文章:

arrays - 不确定如何避免在此处重复代码

c# - 下面的场景是如何分配内存的?我设法把它弄糊涂了

c++ - 在 C++ 中将内存分配给 char*

delphi - 在 Delphi/Win32 中将图像放入组合框(右侧边缘)内

Delphi - 为什么我会收到此访问冲突? ADOQuery 参数有限制吗?

sql - 如何在 Postgresql 中加入 array_agg 列的 View ?

c - 为什么在 fftw 中按行声明复数数组?

c - C语言中的内存管理错误。为什么会出现这些错误?

android - Delphi Android RESTRequest: channel 无法恢复,将被丢弃

德尔福数学: Why is 0. 7<0.70?