一种高效的一种高效的C++固定内存块分配器固定内存块分配器
简介
自定义固定内存块分配器用于解决两种类型的内存问题。第一,全局堆内存的分配和释放非常慢而且是不确定的。你
不能确定内存管理需要消耗多长时间。第二,降低由堆内存碎片(对于执行关键操作的系统尤为重要)造成的内存分
配失败的可能性。
即使不是执行关键操作的系统,一些嵌入式系统也需要被设计成需要运行数周甚至数年而不重启。取决于内存分配的
模式和堆内存的实现方式,长时间的使用堆内存可能导致堆内存错误。
典型的解决方案是预先静态声明所有对象的内存,从而摆脱动态申请内存。然而,由于对象即使没有被使用,也已经
存在并占据一部分内存,静态分配内存的方式会浪费内存存储。此外,使用动态内存分配方式实现的系统提供更为自
然的设计框架,而不像静态内存分配需要事先分配所有对象。
固定内存块分配器并不是一种新的方法。人们已经设计过多种自定义内存分配器很长时间了。这里,我提供的是我在
很多项目中成功使用的,一种简单的C++内存分配器的实现。
这种分配器的实现具有如下特点:
a.比全局堆内存速度快
b.消除堆内存碎片错误
c.不需要额外的内存存储(除了需要几个字节的静态内存)
d.易于使用
e.代码量很小
这里将提供一个申请、释放内存的,包含上面所提到特点的简单类。
阅读完此文后,请同时阅读Replace malloc/free with a Fast Fixed Block Memory Allocator,查看如何使用分配器
Allocator替代CRT(C/C++ Runtime Library)。
回收内存存储
内存管理模式的基本哲学是在对象内存分配时能够回收内存。一旦在内存中创建了一个对象,它所占用的内存就不能
被重新分配。同时,内存要能够回收,允许相同类型的对象重用这部分内存。我实现了一个名为Allocator的类来展示
这些技巧。
当应用程序使用Allocator类进行删除时,对象占用的内存空间被释放以备重用,但却不会立即释放给内存管理器,这
些内存保留在就一个称之为“释放列表”的链表中,并再次分配给相同类型的对象。对每个内存分配的请求,Allocaor类
首先检查“释放列表”中是否存在待释放的内存。只有“释放列表”中没有可用的内存空间时才会分配新的内存。根据所需
的Allocator类的行为,内存存储以三种操作模式使用全局堆内存或者静态内存池。
1.堆内存
2.堆内存池
3.静态内存池
堆内存 vs. 内存池
Allocator类在“释放列表”为空时,能够从堆内存或者内存池中申请新内存。如果使用内存池,你必须事先确定好对象的
数量。确保内存池足够容纳所有需要使用的对象。另一方面,使用堆内存没有数量大小的限制——可以构造内存允许
的尽可能多的对象。
堆内存模式在全局堆内存上为对象分配内存。释放操作将这块内存放入“释放了列表”以备重用。当“释放列表”为空时,
需要在堆内存上创建新内存。这种方式提供了动态内存的分配和释放,优点是内存块可以在运行时动态增加,缺点是
内存块创建期间是不确定的,可能创建失败。
堆内存池模式从全局堆内存创建一个内存池。当Allocator类对象创建时,使用new操作符创建内存池。然后使用内存池
中的内存块进行内存分配。
静态内存池模式使用从静态内存中分配的内存池。静态内存池由使用者进行分配而不是由Allocator对象进行创建。
堆内存池模式和静态内存池模式提供了内存操作的连续使用,因为内存分配器不需要分配单独的内存块。这样分配内
存的过程是十分快速且具有确定性的。
类设计