GetMem 和 AllocMem 有什么区别?

What is the difference between GetMem and AllocMem?

在Delphi中看到几个类似的函数可以用来分配内存,比如GetMem和AllocMem。它们之间有什么区别?

看了文档才发现GetMem分配后不会初始化内存,而AllocMem会。

那么调用GetMem后是否需要初始化内存?医生说是的。但我在某些 Delphi 源代码中看到它们不调用 Initialize。

以及内存使用完毕后是否需要终结?我在一些 Delphi 源代码中看到,他们这样做,但有些事情他们不这样做。

谢谢

逻辑看起来很简单——如果你需要zero-initialized缓冲区,你可以使用AllocMem.

如果您在任何情况下都用自己的数据填充缓冲区,并且从不使用默认内容 - 您可以使用 GetMem.

不同之处在于 AllocMem 用零填充新分配的缓冲区,而 GetMem 不会。如果您的代码要求新分配的缓冲区最初是 all-zeros,您可以使用 AllocMem 而不是手动在缓冲区中写入零;如果你不关心缓冲区中的初始字节,你可以做一个(可能)更便宜的 GetMem.

例如,

var
  p: PByte;
begin
  GetMem(p, 1024);
  try
    p^ := 20;
    (p + 1)^ := 30;
    (p + 2)^ := p^ + (p + 1)^;
    ShowMessage((p + 2)^.ToString);
  finally
    FreeMem(p);
  end;
end;

有效,会一直显示50,但是

GetMem(p, 1024);
try
  p^ := 20;
  (p + 2)^ := p^ + (p + 1)^;
  ShowMessage((p + 2)^.ToString);
finally
  FreeMem(p);
end;

可以显示任何内容——这完全取决于执行代码时 p + 1 处的字节是什么(机会)。

如果您首先用零填充缓冲区,如

GetMem(p, 1024);
try
  FillChar(p^, 1024, 0);
  p^ := 20;
  (p + 2)^ := p^ + (p + 1)^;
  ShowMessage((p + 2)^.ToString);
finally
  FreeMem(p);
end;

您一定会看到 20,因为 p + 1 将保持 0

作为替代方案,您可以这样做

p := AllocMem(1024);
try
  p^ := 20;
  (p + 2)^ := p^ + (p + 1)^;
  ShowMessage((p + 2)^.ToString);
finally
  FreeMem(p);
end;

因为文档保证 AllocMem 将 newly-allocated 缓冲区中的每个字节设置为 0

当然,在堆上手动分配内存是为了 ("advanced") low-level 东西;大多数情况下,你不会那样做。如果你这样做,你应该知道像 internal data formats.

这样的事情

取决于您的需要。您是否只需要一个缓冲区而不关心它最初有什么?使用 GetMem.

GetMem allocates a block of the given Size on the heap, and returns the address of this memory in parameter P. The bytes of the allocated buffer are not set to zero. To dispose of the buffer, use FreeMem. If there isn't enough memory available to allocate the block, an EOutOfMemory exception is raised.

Note: If the memory needs to be zero-initialized, use AllocMem instead.

如果您的逻辑期望该缓冲区的所有字节集都为零,请使用 AllocMem。

AllocMem allocates a block of the given Size on the heap, and returns the address of this memory. Each byte in the allocated buffer is set to zero. To dispose of the buffer, use FreeMem. If there isn't enough memory available to allocate the block, an EOutOfMemory exception is raised.

Note: If the memory does not need to be zero-initialized, it is more efficient to use GetMem instead.

//内存用完后是否需要finalize? 一般在谈论内存分配时,您分配的内存应该始终被释放。

这几乎没有例外 -

  • 当您的对象被引用计数时
  • 当另一个对象照顾一个对象并释放它时