1个回答
展开全部
首先看碎片,32位系统的内存是按“页”管理的,一页内存为64K,只有当前在使用的页面才会在内存中,其他页面不一定总是在内存。因此,分配连续的内存时,当请求少于64K,系统会尽量将其分配在一个内存页面中,当大于64K时,会分配在连续的页面中。以实例说明,例如首先请求30K内存,那么会在第一页分配,第二次请求50K,就必须在第二页面分配。于是第一次返回的地址为0,第二次为64K,30K~64K之间的内存就是所谓的“碎片”。可以将“碎片”简单理解为两块以分配内存之间的空间。当然,“碎片”也可能被利用,但是考虑一种极端的情况:如果一台电脑拥有4G内存,但是每个页面都只分配了32K,那么你将不能申请一片大于32K的内存,即使目前你的物理内存还有2G没有使用。这种情况是很常见的,当程序比较大时如果你没作好这些管理,你会发现new个3~5百MB内存会经常失败。
系统中的new会实施一些算法或者策略,防止内存碎片过快产生,这些算法类似于数据结构中的“堆”,所以new被称之为“堆分配”。但是,系统的堆管理策略是宏观的,通用的。你只要使用它,一定会产生内存碎片。同时,随着堆的规模的加大,会有很多时间浪费在页面在主存与虚拟内存的交换中,这是因为一般情况下,系统返回给你的内存指针是不能改变的,试想你的程序中new了一个新指针,可这片内存不知什么时候被系统换到其他地方了,那么你的程序离奔溃就不远了。这说明在C++中,出现内存碎片后系统是无法执行“碎片整理”的,然而在底层的windows接口中,你能使用“内存句柄”代替指针,内存句柄代表的内存是操作系统管理的而不是地址本身,因此这种情况下操作系统能帮你完成“碎片整理”。只是,内存句柄即使在微软自己的平台上也不及指针通用,各种内库的接口中,绝大部分只认指针,因此你可能在“内存句柄”与指针间不停转换消耗掉程序的时间。
重写内存管理要根据实际需要,这没有统一的方法。最简单的做法是让new返回一个全局数组的地址。全局数组的内存空间在程序启动时就初始化好了,因此你立即就能获取到地址并且这个分配一定是成功的(要是内存耗尽,程序会在启动时挂掉)。全局数组好处在于它的内存一定是连续的,32位系统上能保证2G左右的长度,因此对于操作系统而言可以做到消除碎片,至于如何高效使用这些内存就是程序员的事情了。最后,全局数组的方法也要注意64K对其,否则程序性能会因为内存交换收到影响,特别是当内存使用量很大的时候。
最后,除非程序需要极高的性能,比如大型三维游戏;或者你的程序特别吃内存,比如服务器上的某些服务。你是完没必要重写new delete。
系统中的new会实施一些算法或者策略,防止内存碎片过快产生,这些算法类似于数据结构中的“堆”,所以new被称之为“堆分配”。但是,系统的堆管理策略是宏观的,通用的。你只要使用它,一定会产生内存碎片。同时,随着堆的规模的加大,会有很多时间浪费在页面在主存与虚拟内存的交换中,这是因为一般情况下,系统返回给你的内存指针是不能改变的,试想你的程序中new了一个新指针,可这片内存不知什么时候被系统换到其他地方了,那么你的程序离奔溃就不远了。这说明在C++中,出现内存碎片后系统是无法执行“碎片整理”的,然而在底层的windows接口中,你能使用“内存句柄”代替指针,内存句柄代表的内存是操作系统管理的而不是地址本身,因此这种情况下操作系统能帮你完成“碎片整理”。只是,内存句柄即使在微软自己的平台上也不及指针通用,各种内库的接口中,绝大部分只认指针,因此你可能在“内存句柄”与指针间不停转换消耗掉程序的时间。
重写内存管理要根据实际需要,这没有统一的方法。最简单的做法是让new返回一个全局数组的地址。全局数组的内存空间在程序启动时就初始化好了,因此你立即就能获取到地址并且这个分配一定是成功的(要是内存耗尽,程序会在启动时挂掉)。全局数组好处在于它的内存一定是连续的,32位系统上能保证2G左右的长度,因此对于操作系统而言可以做到消除碎片,至于如何高效使用这些内存就是程序员的事情了。最后,全局数组的方法也要注意64K对其,否则程序性能会因为内存交换收到影响,特别是当内存使用量很大的时候。
最后,除非程序需要极高的性能,比如大型三维游戏;或者你的程序特别吃内存,比如服务器上的某些服务。你是完没必要重写new delete。
追问
我变成没到水平,有点不太清楚你说的呢,呵呵,我在仔细看下
追答
呵呵,,你需要用的时候,,自然就水到渠成啦。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询