本文已经迁移到: http://cpp.winxgui.com/cn:gc-allocator-and-boost-object-pool
C++内存管理变革(4): boost::object_pool
许式伟 (版权声明)
2007-4-21
这篇文章拖的有点久了。NeutralEvil 在3个月之前就在催促我继续写了。只是出于WinxGui完整性的考虑,我一直在刻意优先去补充其它方面的文章,而不是让人去误会WinxGui是一个内存管理库了。:)
言归正传。我们在内存池(MemPool)技术详解已经介绍了boost::pool组件。从内存管理观念的变革来看,这是是一个传统的MemPool组件,尽管也有一定的改进(但只是性能上的改进)。但boost::object_pool不同,它与我在C++内存管理变革强调的观念非常吻合。可以认为,boost::object_pool是一种不通用的gc allocator组件。
我已经多次提出gc allocator的概念。这里仍然需要强调一下,所谓gc allocator,是指具垃圾回收能力的allocator。C++内存管理变革(1)中我们引入了这个概念,但是没有明确gc allocator一词。
boost::object_pool内存管理观念
boost::object_pool的了不起之处在于,这是C++从库的层次上头一次承认,程序员在内存管理上是会犯错误的,由程序员来确保内存不泄漏是困难的。boost::object_pool允许你忘记释放内存。我们来看一个例子:
class X{…};
voidfunc()
{
boost::object_pool<X>alloc;
X*obj1=alloc.construct();
X*obj2=alloc.construct();
alloc.destroy(obj2);
}
如果boost::object_pool只是一个普通的allocator,那么这段代码显然存在问题,因为obj1的析构函数没有执行,申请的内存也没有释放。
但是这段代码是完全正常的。是的,obj1的析构确实执行了,所申请内存也被释放了。这就是说,boost::object_pool既支持你手工释放内存(通过主动调用object_pool::destroy),也支持内存的自动回收(通过object_pool::~object_pool析构的执行)。这正符合gc allocator的规格。
注:内存管理更好的说法是对象管理。内存的申请和释放更确切的说是对象的创建和销毁。但是这里我们不刻意区分这两者的差异。
boost::object_pool与AutoFreeAlloc
我们知道,AutoFreeAlloc不支持手工释放,而只能等到AutoFreeAlloc对象析构的时候一次性全部释放内存。那么,是否可以认为boost::object_pool是否比AutoFreeAlloc更加完备呢?
其实不然。boost::object_pool与AutoFreeAlloc都不是完整意义上的gc allocator。AutoFreeAlloc因为它只能一次性释放,故此仅仅适用特定的用况。然而尽管AutoFreeAlloc不是普适的,但它是通用型的gc allocator。而boost::object_pool只能管理一种对象,并不是通用型的allocator,局限性其实更强。
boost::object_pool的实现细节
大家对boost::object_pool应该已经有了一个总体的把握。现在,让我们深入到object_pool的实现细节中去。
在内存池(MemPool)技术详解中,我们介绍boost::pool组件时,特意提醒大家留意pool::ordered_malloc/ordered_free函数。事实上,boost::object_pool的malloc/construct, free/destroy函数调用了pool::ordered_malloc, ordered_free函数,而不是pool::malloc, free函数。
让我们解释下为什么。
其实这其中的关键,在于object_pool要支持手工释放内存和自动回收内存(并自动执行析构函数)两种模式。如果没有自动析构,那么普通的MemPool就足够了,也就不需要ordered_free。既然有自动回收,同时又存在手工释放,那么就需要区分内存块(MemBlock)中哪些结点(Node)是自由内存结点(FreeNode),哪些结点是已经使用的。对于哪些已经是自由内存的结点,显然不能再调用对象的析构函数。
我们来看看object_pool::~object_pool函数的实现:
template<typenameT,typenameUserAllocator>
object_pool<T,UserAllocator>::~object_pool()
{
//handletrivialcase
if(!this->list.valid())
return;
details::PODptr<size_type>iter=this->list;
details::PODptr<size_type>next=iter;
//Start’freed_iter’atbeginningoffreelist
void*freed_iter=this->first;
constsize_typepartition_size=this->alloc_size();
do
{
//incrementnext
next=next.next();
//deleteallcontainedobjectsthataren’tfreed
//Iterate’i'throughallchunksinthememoryblock
for(char*i=iter.begin();i!=iter.end();i+=partition_size)
{
//Ifthischunkisfree
if(i==freed_iter)
{
//Incrementfreed_itertopointtonextinfreelist
freed_iter=nextof(freed_iter);
//Continuesearchingchunksinthememoryblock
continue;
}
//Thischunkisnotfree(allocated),socallitsdestructor
static_cast<T*>(static_cast<void*>(i))->~T();
//andcontinuesearchingchunksinthememoryblock
}
//freestorage
UserAllocator::free(iter.begin());
//incrementiter
iter=next;
}while(iter.valid());
//Maketheblocklistemptysothattheinheriteddestructordoesn’ttryto
//freeitagain.
this->list.invalidate();
}
这段代码不难理解,object_pool遍历所有申请的内存块(MemBlock),并遍历其中所有结点(Node),如果该结点不出现在自由内存结点(FreeNode)的列表(FreeNodeList)中,那么,它就是用户未主动释放的结点,需要进行相应的析构操作。
现在你明白了,ordered_malloc是为了让MemBlockList中的MemBlock有序,ordered_free是为了让FreeNodeList中的所有FreeNode有序。而MemBlockList, FreeNodeList有序,是为了更快地检测Node是自由的还是被使用的(这实际上是一个集合求交的流程,建议你看看std::set_intersection,它定义在STL的<algorithm>中)。
C++内存管理变革-系列文章
点击这里查看更多内存管理相关文章。
分享到:
相关推荐
在C++中,内存池通过预分配一大块连续内存,并进行精细化管理来替代标准库中的new和delete操作。下面将详细阐述内存池的工作原理以及如何实现一个简单的内存池。 内存池的基本思想是预先分配一大块内存,然后根据...
通过对Slab Allocator与其他几种知名的内核内存分配器进行比较,结果显示,无论是在空间还是时间性能方面,Slab Allocator都表现出了优越性。这是因为它的对象缓存机制减少了不必要的内存分配和释放操作,同时也降低...
BoostPool是一种内存管理工具,它是Boost库的一部分,用于提高C++程序中的内存分配效率。BoostPool基于内存池的概念,提供了一种优化内存分配和释放的方式,尤其在频繁进行小对象分配时,性能提升显著。 BoostPool...
4. **Object Pool**:Boost.Object Pool是Pool Allocation的一种扩展,支持对象级别的内存池管理。不同于普通的内存池只管理原始字节,对象池可以处理特定类型的对象,进一步优化内存分配和回收。 5. **Allocator ...
10. **C++标准库中的内存管理**:`std::allocator`是C++标准模板库的一部分,提供了一种通用的方式来管理内存。此外,`std::vector`, `std::list`等容器也实现了自动内存管理。 “Memory Management: Algorithms ...
结合网上版本及c++ primer及visual sudio2017,ubuntu 16.04实测,实现标准库中vector的实现,缺少部分函数,包含了主要的push_back,resize,reserve,[],size()函数,若有疑问请发送至2268047160@qq.com,最近在详细...
在C++编程中,内存管理是一项关键任务,尤其是在开发高性能和高并发的系统时。ACE(Adaptive Communication Environment)库提供了一组高级的内存管理工具,使得开发者能够更有效地管理和控制内存分配。以下是对ACE...
2. **内存分配器**:提供了多种内存分配模式的分配器,如池分配器(`pool_allocator`),以优化性能和减少内存碎片。 3. **直接 I/O 流格式化**:`vectorstream` 和 `bufferstream` 类提供了高效的数据序列化和反...
虽然在大多数情况下,开发人员并不需要直接与`Allocator`交互,但在某些特定场合下,通过自定义`Allocator`来优化内存管理仍然是一个非常有用的技能。希望本文能够帮助读者更好地掌握这一知识点,并在未来的项目中...
在C++编程中,内存管理是一项至关重要的技能,它直接影响程序的性能、稳定性和资源利用率。本主题将深入探讨C++中的内存管理算法及其实现,包括动态内存分配、内存释放、内存泄漏检测以及优化策略。 首先,我们关注...
链接列表分配器文档用法在您的根模块中创建一个静态分配器:uselinked_list_allocator :: LockedHeap; #[global_allocator]的链表分配器文档用法在您的根模块中创建一个静态分配器:uselinked_list_allocator :: ...
linux下c++ allocator 共享内存,内存池实现
它在多个平台上的Mozilla Firefox浏览器、FreeBSD与NetBSD操作系统以及Facebook的部分组件中作为默认的内存管理器。然而,尽管jemalloc应用如此广泛,针对其安全漏洞的研究却相对较少。本研究旨在深入探讨jemalloc的...
std::allocator 是 C++标准库中提供的默认分配器,他的特点就在于我们在 使用 new 来申请内存构造新对象的时候,势必要调用类对象的默认构造函数 而使用 std::allocator 则可以将内存分配和对象的构造这两部分...
C++ 是一种强大的编程语言,其内存管理是其核心特性之一。内存管理涉及到如何有效地分配、使用和释放内存,以确保程序的高效运行和避免内存泄漏。本资料“C++ 内存管理算法和实现”深入探讨了这个主题,特别关注了...
当需要扩展容量时,`vector`会调用`Allocator`(如`std::allocator`)分配新的内存,并通过`memcpy`等函数复制旧元素到新内存区域。 4. **迭代器**: `vector`提供两种迭代器:`iterator`和`const_iterator`,用于...
**动态内存池(Dynamic Memory Pool)与动态分配器(Dynamic Allocator):** 在提供的`dynamicmempool.h`和`dynamicallocator.h`文件中,很可能是实现了动态内存池和基于此内存池的STL分配器。动态内存池允许在运行...
总之,通过自定义`std::allocator`,开发者可以根据具体应用需求来优化内存管理,从而提升C++程序的性能。这种方法需要对内存管理有深入的理解,但一旦实现得当,它可以显著减少堆碎片,提高内存分配速度,对于那些...
### C++内存管理创新:GC Allocator #### 引言 在C++编程中,内存管理一直是一个关键且复杂的任务。大多数C++程序员不得不手动管理内存,包括分配和释放内存资源,这不仅耗时而且容易出错。随着软件工程的发展,...