内存分配不管怎样,最终底层都会调用到c库的 malloc()函数,然后再根据操作系统的不同区调用更底层的部分
上图左上角 VC中,源代码可以看到 new是调用malloc的。
malloc真正给你的部分是下图这样的 :
蓝色的部分你懂的 :void *malloc(size_t size)
size是内存块的大小,字节为单位
- 上下的红色是cookie
- 绿色部分是调整到某个边界。
这些细节在侯老师的课《内存管理》中会介绍?
所以malloc给你的比你申请的大小还多了不少东西。
附加的东西是基本不变的。
所以你申请的越大,附加的东西的 比例就越小。
如果称附加的东西为额外的开销overhead的话。
小块内存的overhead比例就更大
VC6 的STL中的分配器:
VC6的标准库的分配器实现在<xmemory
>中:
本机V2017的xmemory在路径:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.11.25503\include\xmemory
和
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\include\xmemory
分配器最重要的两个函数,allocate和deallocate
在BC5 STL中: (波楞C)
接下来是gnu C:
这里的右下角的注释是说,虽然gnuC实现了这里的分配器,但是容器中并没有使用这个。想必是使用了更好的分配器。
使用中:
这就呼应了上面说的不是用的这个。
护体实现是这样的:
所以他主要的诉求是减少malloc的次数,因为malloc就带着额外开销overhead。
回到前面那张malloc实际分配的图:
上下红色的被称为cookie,用来记录分配的大小,这样在释放内存的时候,就明确释放范围。
所以free这块内存时候就从cookie知道它要回收多大的内存。
那么为什么cookie要上下都有(消耗了8个字节)呢?一般的会想,不是只要上面有就好了吗?上下的值都是一样的。
这些内容在内存管理在去提他。
由于容器的每个元素大小固定的,所以似乎不需要cookie部分,所以gnuC就从这里着手,它不要cookie,尽量减少malloc 的次数。
如果一个容器申请100万个元素,那么省掉cookie就可以省下800万个字节的大小。(省不了这么多,变成没有cookie的这些小块)。
当然也有小缺陷,看源码才知道,放到内存管理去讲,不管这缺陷不会有太大的影响。
看下图:
每个#n
节点负责 n*8个字节的大小。即从左往右按照8 的倍数增长。
容器的元素大小会被调整到8 的倍数
gnuC4.9版的STL的分配器:
可以看到又回到到调用malloc和free的情况。不如gnuC2.9的设计(alloc
)。
新版本还在,换了个名字,__pool_allocate
就是2.9版本的alloc
所以你要用他,也可以使用: