如何找到指针引用的内存大小?

Mas*_*ler 8 delphi pointers memory-management

GetMem允许您分配任意大小的缓冲区.在某处,大小信息由内存管理器保留,因为当您将指针传递给FreeMem时,不需要告诉它缓冲区有多大.

该信息仅供内部使用,还是有任何方法可以检索指针指向的缓冲区大小?

Del*_*ics 8

似乎GetMem()返回的指针引用的块的大小必须可以从某个地方获得,因为FreeMem()不要求您确定要释放的内存大小 - 系统必须能够确定那,为什么不是应用程序开发人员呢?

但是,正如其他人所说,所涉及的内存管理的确切细节并非由系统本身定义.... Delphi一直有可替换的内存管理器架构,并且为兼容的内存管理器定义的"接口"不需要他们为任意指针提供此信息.

默认的内存管理器将以任何适合它的方式维护必要的信息,但是其他一些内存管理器几乎肯定会使用完全不同的(如果表面上相似的)机制,所以即使您基于对一个内存管理器的深入了解而破解解决方案,如果您更改内存管理器(或者如果您更改了内存管理器,例如通过系统定义的更改,默认情况下您可能正在使用的内存管理器,例如Delphi 2005和2006之间发生的那样)那么您的解决方案几乎肯定会打破.

一般来说,RTL /内存管理器的一个不合理的假设是,应用程序应该已经知道GetMem()分配指针引用的内存有多大,因为应用程序首先要求它!:)

如果您的应用程序没有分配指针,那么您的应用程序的内存管理器绝对无法知道它引用的块有多大.例如,它可能是指向某个较大块的中间的指针- 只有指针的源可能知道它与它引用的内存的关系!

但是,如果您的应用程序确实需要维护有关它自己的指针的信息,那么它当然可以通过一个简单的单例类或函数库轻松设计实现这一点的方法,GetMem()/FreeMem()请求通过它来路由,保持每个当前分配的指针的相关请求大小的记录.这样的机制当然可以根据需要轻松地公开这些信息,完全可靠地并且独立于正在使用的任何存储器管理器.

如果需要" 准确 "记录,这可能是唯一的选择,因为给定的存储器管理器实现可以为给定大小的数据分配比实际请求更大的存储器块.我不知道是否有任何内存管理器确实这样做了,但为了提高效率,它可以在理论上这样做.


Fra*_*ois 5

它供内部使用,因为它取决于所使用的MemoryManager.顺便说一句,这就是你需要使用同一个MemoryManager中的GetMem/FreeMem对的原因; 没有规范的方式来了解内存是如何被保留的.
在Delphi,如果你看FastMM4,可以看到的是,存储器被在小型,中型或大型块分配:
所述小块在固定大小的块的池分配(块大小在块类型池级别定义)

  TSmallBlockType = packed record
    {True = Block type is locked}
    BlockTypeLocked: Boolean;
    {Bitmap indicating which of the first 8 medium block groups contain blocks
     of a suitable size for a block pool.}
    AllowedGroupsForBlockPoolBitmap: byte;
    {The block size for this block type}
    BlockSize: Word;
Run Code Online (Sandbox Code Playgroud)

所述介质块也被分配在池中,但是具有可变的大小

  {Medium block layout:
   Offset: -8 = Previous Block Size (only if the previous block is free)
   Offset: -4 = This block size and flags
   Offset: 0 = User data / Previous Free Block (if this block is free)
   Offset: 4 = Next Free Block (if this block is free)
   Offset: BlockSize - 8 = Size of this block (if this block is free)
   Offset: BlockSize - 4 = Size of the next block and flags

  {Get the block header}
  LBlockHeader := PCardinal(Cardinal(APointer) - BlockHeaderSize)^;
  {Get the medium block size}
  LBlockSize := LBlockHeader and DropMediumAndLargeFlagsMask;
Run Code Online (Sandbox Code Playgroud)

大块与所需尺寸分别分配

  TLargeBlockHeader = packed record
    {Points to the previous and next large blocks. This circular linked
     list is used to track memory leaks on program shutdown.}
    PreviousLargeBlockHeader: PLargeBlockHeader;
    NextLargeBlockHeader: PLargeBlockHeader;
    {The user allocated size of the Large block}
    UserAllocatedSize: Cardinal;
    {The size of this block plus the flags}
    BlockSizeAndFlags: Cardinal;
  end;
Run Code Online (Sandbox Code Playgroud)