STL学习笔记(三):空间配置器

本文解析了STL中的两级空间配置器机制。第一级配置器使用C语言的内存管理函数,并模拟C++的set_new_handler机制。第二级配置器通过free_list管理和分配小块内存,同时介绍了记忆池如何为free_list提供空间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们首先来看一下STL空间配置器中的第一级和第二级配置器:
这里写图片描述

第一级配置器:_malloc_alloc_template

_malloc_alloc_template直接使用C语言中的malloc、free和realloc进行申请、释放和重新申请的操作,并且在内存空间不足情况下模拟C++的set_new_handler()。

什么是set_new_handler机制?
当内存空间不足的情况下,不是直接抛出 bad_alloc,而是先执行一个处理的涵式,这个涵式就是set_new_handler。这个机制下,有机会释放其他的记忆体来给当前申请使用。如果失败了才会继续执行抛出 bad_alloc的操作。

为什么不能直接使用C++的set_new_handler?
因为SGI的STL中配置空间使用的是malloc并非采用new,所以就不能使用C++里面的set_new_handler机制。

第二级配置器:__default_alloc_template

__default_alloc_template拥有一个配置涵式:allocate()。allocated首先判断申请空间的大小,如果大于128bytes就呼叫第一级配置器,如果小于128bytes就检查对应的 free_list。如果 free_list 之内有可用的块儿就直接用,如果没有可用的块儿就将区块儿上调至8的倍数,然后呼叫refill(),准备为 free_list 重新填充空间。

第二级配置器维护 16 個 free_lists,各自管理大小分別为 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128 bytes。(都是8的倍数)

因为这些free_list中需要指针来指向链表的下一个节点,为了节省额外的指针开销,我们使用了union。free_list节点结构如下:

 union obj { 
     union obj * free_list_link;        
     char client_data[1];    /* The client sees this. */ 
};

记忆池

记忆池用来给 free_list 提供块儿。这些工作是由chunk_alloc()函数完成的,并且如果记忆池水量充足时,都是一次拿出20块儿大小,除了给客户使用的,剩下的都放在free_list中。
注意:当记忆池为空的时候,如果 free_list 继续像记忆池申请空间,那么记忆池会申请两倍的空间大小,并将其中一半给 free_list,另一半存在记忆池中。(所以初次申请空间的时候一定是申请两倍的,因为记忆池初始为空)

我们举例说明记忆池的工作方式:
程序一开始,客户申请32字节大小的空间,此时free_list[3]为空,调用 chunk_alloc(32, 20),于是记忆池malloc了40个32bytes的区块儿,其中第一个交出,另19个交给free_list[3]维护,剩下的20个留在记忆池中。接下来客户呼叫chunk_alloc(64, 20),free_list[7]为空,请求记忆池,而记忆池只能提供10个块儿(32*20/64=10)。第一个给客户,另9个给free_list[7]维护,记忆池为空。如果接下来继续chunk_alloc(96, 20),此时free_list[11]为空,记忆池也为空,于是记忆池malloc了40+n(附加量)个96bytes的区块,第一个交出,另19个给free_list[11]维护,剩余20+n存在记忆池中。

注意:如果整个系统的heap空间都不够了,那么记忆池的malloc操作就会失败,chunk_alloc就会到处寻找有没有空闲的free_list,如果有交出,如果没有呼叫第一级配置器,第一级配置器也是使用malloc,但是第一级配置器有 out_of_memory机制(模拟C++的new_handler机制),这个机制有机会释放其他记忆体来使用,如果可以则成功,否则抛出bad_alloc异常。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值