装载BDS2006内存管理器

转载:  作者(Pierre le Riche)

簡介

Delphi 2006中Win32的内存管理员已经被一个更快速,更多功能的新的内存管理员所取代。 本文是这个新的内存管理员新功能的结论并且讨论如何使用这个新的内存管理员。 本文解释了新的内存管理员是如何被实作的,以及新的设计如何影响了内存管理员的执行行为,以及它如何影响了由Delphi 2006编译的应用程序的执行行为。

    新功能

    大型内存地址空间的支持(Large Address Space Support)

新的内存管理员现在支持大于2GB(最大到4GB)的内存寻址空间。

    改善的程序区块对齐功能(Improved Block Alignment)

现在由内存管理员回传的内存块都是至少以88个字节为单位做为对齐的边界。您也可以藉由执行下面的程序代码: SetMinimumBlockAlignment(mba16Byte)来强迫使用以16个字节为单位对齐的边界。

    智能型重分配地址(Intelligent Reallocations)

重分配地址现在是以智能型的方式来处理的。新的内存管理员现在会尽可能的避免移动内存区块,除非移动内存区块的好处超过了要付出的成本。

    改善的锁定细致度(Improved Locking Granularity)

和以前的内存管理员比较来,现在的内存管理员拥有较细微的锁定细致度,因此对于密集使用内存管理员的多执行绪应用程序而言,将会看到有明显的执行效率的增加。

    改善的内存碎片行为(Improved Fragmentation Behaviour)

由于改善的内部管理架构,内存空间碎片的问题将会比先前的内存管理员好上许多。

    简化的内存管理员分享机制(Simplified Memory Manager Sharing Mechanism)

一个新的内存管理员分享机制被引入而避免了需要使用borlndmm.dll 函式库,虽然新的内存管理员仍然支持旧的的分享机制。(请参考SimpleShareMem.pas 程序单元以了解更多的细节。)

    内存漏失报告(Memory Leak Reporting)

允许应用程序注册(和解除注册)期望的内存漏失,并且可以选择性的在应用程序结束时报告任何未预期的内存漏失。

    扩充的状态报告(Extended State Reporting)

新的内存管理员拥有扩充的状态报告功能,它允许追踪对于每一种的区块大小进行地址空间的使用次数统计,以及内存管理员的执行使用效率。(使用效率是根据已经配置的地址空间而由于区块管理架构和碎片而浪费的比率来测量的。)

    指定最小程序区块对齐功能(Specifying Minimum Block Alignment)

由内存管理员回传的最小对齐的区块是8个字节。在目前的实作中,所有大于148个字节的请求都至少以16个字节做为对齐的单位。 要强迫所有新的配置都以16个字节做为对齐的单位, 请执行SetMinimumBlockAlignment(mba16Byte)。 要回复内定的8字节对齐, 请执行 SetMinimumBlockAlignment(mba8Byte)。

    允许大于2GB的寻址功能(Enabling An Address Space > 2GB)

要使用大于2GB的地址空间有三个先决的条件:

    支持的操作系统(A Supported Operating System)

需要一个支持大于2GB使用者模式地址空间的Windows操作系统版本。目前可以是Windows x64 版本, 或是 32-位的 Windows XP/2003,并且在 boot.ini 档案中使用/3GB选项。

    适当的连结器编译器指令(Appropriate Linker Directive)

IMAGE_FILE_LARGE_ADDRESS_AWARE 旗帜必须在EXE的表头信息中设定以通知Windows这个应用程序支持大于2GB的地址空间。 这个旗帜可以藉由在项目的.dpr档案中指定{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE} 编译器指令来设定。

    第3方控件和函式库的支持(Third Party Component And Library Support)

所有的函式库和第3方控件都必须支持大型地址空间。由于2GB的地址空间需要设定指针的最高位值为0,因此一个大型的地址空间可能会让先前没有任何错误征兆的软件产生指针运算的臭虫。通常这些臭虫都是由于在进行指针运算/指针比较等工作时,把指针转换为整数而不是转换为cardinals 而产生的。

    报告内存漏失(Reporting Memory Leaks)

新的内存管理员拥有报告任何在应用程序结束时尚未释放的内存区块的能力,也就是报告内存漏失的能力。在某些情形下是故意让内存有漏失的现象,因此也可以关闭内存管理员报告这种的内存漏失情形。对于这种情形,有一个称为RegisterExpectedMemoryLeak的函式,它接受一个指到漏失的内存区块的指针,由RegisterExpectedMemoryLeak注册的漏失便不会出现在内存漏失的报告中。

内存漏失报告在内定上是关闭的,但是可以藉由设定全域变量 ReportMemoryLeaksOnShutdown为”True”来激活它。如果没有任何未预期的内存漏失,那么messagebox便不会显示,即使是在ReportMemoryLeaksOnShutdown设定为”True”的情形下。一个有用的程序代码片断,它可以让应用程序在执行于除错器中时开启内存漏失报告是”ReportMemoryLeaksOnShutdown := DebugHook <> 0” 。

请注意漏失注册数据库被限制为16K的大小,因此RegisterExpectedMemoryLeak函式可能会执行失败并且回传False。请呼叫UnregisterExpectedMemoryLeak 以便从数据库中移除已有的资料。

下面即是一个内存漏失报告的范例(在一个应用程序结束执行时显示出来的):

Hide image

而这是造成内存漏失的程序代码:

Hide image

    报告内存管理员状态(Reporting Memory Manager State)

新的内存管理员和以前的内存管理员完全兼容,因此也支持GetHeapStatus 呼叫,并且提供了两个新的叙述报告函式以提供更多的细节:

    GetMemoryManagerState

回传所有内部区块大小以及每一个区块配置次数的列表。同时也回传为每一个内部区块大小保留的地址空间的数量,如此一来区块成本以及内存池碎片的情形就可以被测量。

    GetMemoryMap

回传所有在地址空间中64K大小的区块列表以及这些64K区块被使用的状态,例如尚未使用,已经被业界标准配置或保留,或是被Delphi内存管理员所使用。

    在应用程序和函式库之间分享内存管理员(Sharing Memory Managers Between An Application And Libraries)

在以前的版本中,于应用程序和它的函式库之间分享内存管理员的机制是藉由ShareMem.pas 程序单元以及borlndmm.dll 函式库。 这个方法在新的内存管理员中仍然支持,而且旧的borlndmm.dll 函式库以及新的,高效率的borlndmm.dll是同时被使用的。

新的内存管理员同时也加入了一个新的可选择使用的分享选项,以允许不使用任何外部的函式库。这种方法是藉由两个函式呼叫来达成的:

    AttemptToUseSharedMemoryManager

此函式会搜寻目前的执行程序来找寻分享的内存管理员。如果目前没有任何由内定内存管理员配置的内存,那么模块便会转向使用分享的内存管理员。这个函式会在找到另外的内存管理员并且模块成功的切换到找到的内存管理员之后回传True。

    ShareMemoryManager

此函式可以让模块的内存管理员和目前执行程序中其它的模型分享。每一个执行程序只有一个内存管理员可以分享,所以此函式可能会执行失败。 (并且回传false)。

新的SimpleShareMem.pas 程序单元实作了这个新的分享机制,并且可以直接取代ShareMem.pas。

    使用其它可取代的内存管理员(Using Replacement Memory Managers)

如同以前的版本,内存管理员可以被第3方的内存管理员所取代。为了让第3方的内存管理员也实作由本版本所提供的新功能, SetMemoryManager程序也被复载了以接受新的TMemoryManagerEx 记录(Record)数据结构。TMemoryManagerEx记录藉由加入了下面的三个字段扩展了旧的TMemoryManager 记录:

    AllocMem

这个字段应该指到可以回传使用0填满的请求的区块大小的函式。

    RegisterExpectedMemoryLeak

这个字段应该指到一个预期内存漏失的函式。如果内存漏失检查和报告没有被取代的内存管理员所实作,那么这个字段可以指到一个回传”False”的函式。

    UnregisterExpectedMemoryLeak

这个字段应该指到一个降除先前注册预期内存漏失的函式。如果内存漏失检查和报告没有被取代的内存管理员所实作,那么这个字段可以指到一个回传”False”的函式。

对于使用旧的TMemoryManager记录的较为老旧的内存管理员而言,有内定的AllocMem, RegisterExpectedMemoryLeak 和 UnregisterExpectedMemoryLeak 处理函式会被安装。内定的AllocMem 处理函式只是简单的呼叫GetMem然后清除内存区块,而内定的RegisterExpectedMemoryLeak 和 UnregisterExpectedMemoryLeak则只是回传”False”而已。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值