C/C++内存池管理机制

GNU C内存池管理机制

在不同编译器中,malloc/free内存管理的实现方式有所区别,但都是使用的内存池机制进行管理。本小节介绍在GNU C中的内存池管理,通过阅读可以学习到以下内容:


下面详细介绍。

1.为什么使用内存池管理内存

我们经常使用下面的语句进行malloc的内存分配:

data_t* ptr = (data_t*)malloc(sizeof(data_t));

但是,对于计算机而言,我们使用的内存空间真的就只有 sizeof(data_t) 字节吗?

显然不是的。在调用malloc内存分配器时,为了程序调试与内存回收,标准库会在分配的内存块上下加上cookie信息,其中包括了大小为1byte的上下内存屏障gap、调用的文件名称、用户申请的空间大小等等。

这些信息的大小是一个常量,也就是说,每调用一次malloc,标准库将在其申请空间上追加cookie内存空间。这就造成了内存空间的浪费,申请的空间越小,浪费的空间占比越大。

因此,标准库使用内存池进行内存管理。一次性分配一大片内存,并交由内存池管理器进行管理;而用户进行空间申请时,标准库只需要在内存池中分配出相应大小的内存即可,不需要额外添加cookie信息。这极大的提高了内存的有效使用率。

那么,标准库如何设计内存池呢?

2.内存池的底层结构设计

内存池底层使用的16个内存块链表头进行管理,如下图所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dmDFnr3R-1621240650725)(C:\Users\libHong\AppData\Roaming\Typora\typora-user-images\image-20210517151646154.png)]

其中,内存以8字节对齐,对应标号#0#16管理的内存为8128 byte,例如#3管理的内存块大小为4*8 byte = 32 byte。

同时,每个链表中的每个结点均使用union进行设计,如下所示。

union obj{
    union obj* free_list_link;
    char data[1];   // 作为指针使用,这样设计可以自动初始化,防止core dump
};

使用union设计的好处

  1. 当分配内存时,直接将data指向相应的内存,写入数据即可,此时free_list_link就被覆盖,不需要相应的后继指向;

  2. 当回收内存时,直接将free_list_link指向相应的后继指针,而无须管理data中的数据;

这样减少了额外的指针空间,提高了内存空间的使用率。

3.内存池如何管理内存

下面使用例子进行介绍。最开始,内存池内存空间只有free_list[16]链表头,而没有实际内存空间。

在这里插入图片描述

1.假设用户申请空间16 byte时,系统将申请一大片空间,其大小为:
s i z e = 40 ∗ 16 + r o u n d _ u p ( b y t e ) ; size = 40 * 16 + round\_up (byte); size=4016+round_up(byte);
其中round up为上一次申请空间累计大小右移4位得到,如总空间为1280 byte,则
r o u n d _ u p = 1280 > > 4 ; round\_up = 1280>>4; round_up=1280>>4;
为何为40*16呢? 为了防止用户重复申请相同大小空间,出现冗余操作;系统每次会将申请的空间分为 20 个用户申请的空间 16byte,然后将后面的内存空间用于下次操作。最后,将第一个 16 byte内存空间返回给用户,并将内存块交给#2号链表头管理,如下图所示。
在这里插入图片描述

2.接着,用户申请空间16byte时,系统会在内存池里面查找有没有多余的内存空间。若有,直接返回;否则,进行申请返回。此时,内存池中存在,则进行下面操作。
在这里插入图片描述

3.若用户申请空间8byte空间时,此时内存池空间存在内存空间,但是不存在划分为8byte的小内存块,则进行下面操作。
在这里插入图片描述

4.当用户申请空间不是8的整数倍,则系统会向上对齐进行分配空间,如用户申请空间为1byte,则系统将进行下面操作。
在这里插入图片描述

5.当用户释放空间时,内存空间将会放回内存池,如下所示。
在这里插入图片描述
6.当用户申请64字节空间时,在未切割的内存块中进行切割,并返回。

注意:

1.内存池申请空间有一定的限制,系统分配总量不能超过该限制,否则会出现分配空间异常。

2.当申请的空间大于128byte时,系统不再使用该内存池进行管理,而是直接使用malloc进行分配空间。

本文仅供学习使用,参考侯捷老师的内存管理。若存在问题,欢迎大家指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值