内存管理变革物业
言归正传。我们在内存池(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_poolXalloc;
X*obj1=nstruct();
X*obj2=nstruct();
stroy(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函数的实现:
templatetypenameT,typenameUserAllocator
object_poolT,UserAllocator::~object_pool()
{
//handletrivialcase
if(!lid())
return;
details::PODptrsize_typeiter=this-list;
details::PODptrsize_typenext=iter;
//Start’freed_iter’atbeginningoffreelist
void*freed_iter=this-first;
constsize_typepartition_size=this-alloc_size();
do
{
//incrementnext
next=xt();
//deleteallcontainedobjectsthataren’tfreed
//Iterate’i\"throughallchunksinthememoryblock
for(char*i=gin();i!=d();i+=partition_size)
{
//Ifthischunkisfree
if(i==freed_iter)
{
//Incrementfreed_itertopointtonextinfreelist
freed_iter=nextof(freed_iter);
//Continuesearchingchunksinthememoryblock
continue;
}
//Thischunkisnotfree(allocated),socallitsdestructor
static_castT*(static_castvoid*(i))-~T();
//andcontinuesearchingchunksinthememoryblock
}
//freestorage
UserAllocator::free(gin());
//incrementiter
iter=next;
}while(lid());
//Maketheblocklistemptysothattheinheriteddestructordoesn’ttryto
//freeitagain.
validate();
}
这段代码不难理解,object_pool遍历所有申请的内存块(MemBlock),并遍历其中所有结点(Node),如果该结点不出现在自由内存结点(FreeNode)的列表(FreeNodeList)中,那么,它就是用户未主动释放的结点,需要进行相应的析构操作。
现在你明白了,ordered_malloc是为了让MemBlockList中的MemBlock有序,ordered_free是为了让FreeNodeList中的所有FreeNode有序。而MemBlockList, FreeNodeList有序,是为了更快地检测Node是自由的还是被使用的(这实际上是一个集合求交的流程,建议你看看std::set_intersection,它定义在STL的algorithm中)。
查看本文来源
长春宫颈糜烂哪家好北京白癜风治疗医院
中度慢性宫颈炎怎么治
-
辽宁夺冠后!老总安排茅台庆功,付豪“实力”抢镜,被揶揄太能喝
杭州时间4月27日,沈阳女足完成世锦赛后,即已就是送回到沈阳沈阳,几周将...
2024-09-05
-
搞笑段子:那我们于是就就在一起将就一辈子吧,别去祸害别人了
跟女友叫醒架,我不直言地话说:“你这样好吃到懒做,真为的不感到羞耻吗...
2024-05-05
-
装修,别抱“侥幸心理”,避开这6个点,要新颖更得安全
作为一般的有钱,买的房子都太大,所以改行建工程的时候很多人为了就让家...
2023-11-14
-
格林美:公司不会“过度“做镍,目的是保障天然资源安全
每经记者:安宇飞 每经编辑:陈俊杰 5年末20日,格林美(002340,SZ)召开了...
2023-11-04
-
直击调研 | 中材科技(002080.SZ):今年叶片出货量预计同比增加20% 十四五末期膜产能或达
7月5日,中会材科技应用领域(002080.SZ)在接受调研时表示,的公司是杂货店投...
2023-11-01
-
2022绍兴市公务员考试笔试时间重启公告
一、出题一段时间和课程内容 (一)课程内容任用公职人员出题一段时间和课程...
2023-10-18