我想用一个字节数组分配空间(动态大小)并获得一个指向“空间区域”的指针,如果我不再需要它,以后再释放它。
我知道 VirtualAlloc、VirutalAllocEx 和 LocalAlloc。哪个是最好的,之后如何释放内存?
谢谢您的帮助。
我想用一个字节数组分配空间(动态大小)并获得一个指向“空间区域”的指针,如果我不再需要它,以后再释放它。
我知道 VirtualAlloc、VirutalAllocEx 和 LocalAlloc。哪个是最好的,之后如何释放内存?
谢谢您的帮助。
我认为使用 winapi 而不是本机 Pascal 函数不是一个好主意。
您可以简单地将字节数组定义为
var yourarray: array of byte;
那么它可以分配给
setlength(yourarray, yoursize);
并被释放
setlength(yourarray, 0);
这样的数组是引用计数的,您可以访问单个字节yourarray[byteid]
或者如果你真的想要指针,你可以使用:
var p: pointer;
GetMem(p, yoursize);
FreeMem(p);
您应该更好地使用GetMem/FreeMem
或动态数组,或RawByteString
. 请注意GetMem/FreeMem
,动态数组或RawByteString
使用堆而不是堆栈进行分配。
使用VirtualAlloc/VirtualFree
而不是没有兴趣GetMem/FreeMem
。对于大块,内存管理器(实现堆)将调用VirtualAlloc/VirtualFree
API,但对于较小的块,它将更加优化以依赖堆。
由于VirtualAlloc/VirtualFree
对于当前进程是本地的,使用它的唯一兴趣是如果您想创建一些能够执行代码的内存块,例如,通过它们的VirtualAllocEx/VirtualFreeEx
API 创建一些类或接口的存根包装器(但我怀疑这是您的需要)。
如果你想对所有进程/程序使用一些全局内存,你GlobalAlloc/GlobalFree
手头有 API 调用。
VirtualAlloc 是一个页面分配函数。它是用于分配内存的低级用户空间代码函数。但是你必须明白,从 VirtualAlloc 返回的内存是对齐到页面大小的倍数的。
在 Windows 32 位上,页面大小通常为 4096 字节。在其他系统上,它可能更大。
因此,当您需要整页内存时,这使得 VirtualAlloc 很有用。VirtualAlloc 可以分配大的“页面范围”。这些页面是虚拟的,因此实际上是到底层系统 RAM 的映射,并且有一半的时间被换出到交换文件,这就是为什么它被称为 VirtualAlloc,强调虚拟。
使用 VirtualAlloc 和 VirtualAllocEx 你也可以只保留一些内存页面。保留页面是在您确定它们将被使用之前保持在保留状态的范围,此时您可以提交页面,此时将分配/提交页面所需的底层资源。
使用 VirtualFree 释放您使用 VirtualAlloc 分配或保留的页面。
VirtualAlloc 和 LocalAlloc 之间的区别在于 LocalAlloc 从堆中分配,而堆是从更大的保留页面块分配内存块的机制。在内部,堆使用 VirtualAlloc 分配大部分内存,然后将这些页面分成较小的块,您可以将这些块视为从 malloc、getmem 和 LocalAlloc 等函数返回的缓冲区。
LocalAlloc 可以看作是 Windows 内置的 malloc 或 getmem 版本。对 LocalAlloc 的调用类似于在 C++ 中调用 malloc 或在 Delphi 中调用 getmem。事实上,您可以在 Delphi 中覆盖 GetMem 并使用 LocalAlloc,您的 DElphi 应用程序可能会运行相同。
调用 LocalFree 以释放一些使用 LocalAlloc 分配的内存。在内部,这会将内存块标记为可供下一个调用者使用。
因此,现在决定时的主要考虑因素是开销。如果您需要经常分配,那么您应该使用 LocalAlloc 或 getmem,因为提交和保留虚拟页面是一个更耗时的过程。
换句话说,使用 getmem 或 LocalAlloc 除非您有非常特殊的理由不这样做。
在我使用 Delphi 5 与 C++ 编译器的所有测试中,Delphi 5 getmem 更快,尽管那是五年前的事了。从那时起,像hoard 这样的分配器就可以使用,它可能会更快。但是当有这么多变量时,很难说什么更快。
但是可以肯定的是,像 LocalAlloc、malloc 和 getmem 这样的所有堆函数应该比使用 VirtualAlloc 分配和释放要快得多,VirtualAlloc 通常用于在内部为 LocalAlloc 和 getmem 等堆函数保留内存。
对于 Pascal 程序,更喜欢 getmem 或 SetLength,因为它更便于移植。或者,您可以将自己的包装函数写入 LocalAlloc 或任何 OS 堆函数。
您列出的函数是 WinAPI 函数,它们是平台相关的。显然,您应该使用用于分配的相同 API 的功能来解除分配。
如果您想使用 Delphi 内存管理器,那么 GetMemory 和 FreeMemory 是显而易见的选择,但是如果您需要将指针与系统页面大小对齐(这是某些低级库的要求)或者您将使用大缓冲区大小,那么 Windows API 虚拟内存函数VirtualAlloc和 VirtualFree 是你最好的朋友。