之前说道alloc是原G2.9版本的默认的分配器,这篇就把alloc的原理梳理梳理,顺便简单介绍下有关的内存管理。

  一般而言,我们通常习惯的内存分配操作和释放操作是这样的:

    class Foo {…};

    Foo* p = new Foo;   // 分配内存,然后构造对象

    Delete p;           // 将对象析构, 然后释放内存

  这里的内存分配操作由alloc::allocate()负责, 内存释放操作由alloc::deallocate()负责。

当我们申请的内存很小时,那么new(只是对malloc进行简单的包装)的空间便会形成一定程度的浪费,为什么这么说?我们先来看看基本的内存分配:

       

    (图片来自于侯捷老师的课程《内存管理》,侵删)

  当我们申请10个int对象时,内存分配的空间其实不是10 * 4 = 40个字节这么简单. 如图所示(调试状态下)最上边和最下边的两个cookie(用来记录分配空间的大小)4*2 = 8, 橙色的是Debug状态下申请出的空间帮助Debug,为32 + 4 = 36.而中间部分才为你要申请的10 * 4 = 40个字节,将这些数据加起来40 + 8+36 = 84,而pad那部分则是编译器进行自动补齐,将字节数调整成16的倍数,于是84 + 12 = 96.也就是说你只申请了10个int,而编译器却给你返回96个字节的空间,很神奇是不是?当然重点不是这里,想一下,如果我们只需要申请1个int呢?而上下两个cookie就占了8个字节,是不是很浪费?

  为了考虑小型区块可能造成的浪费及内存破碎问题,SGI设计了双层级分配器,第一级分配器直接使用malloc()和free()。第二级分配器则视情况采取用不同的策略,当分配空间大于128个字节时调用一级分配器,小于128字节时,便采用更复杂的内存池管理方式,也就是alloc。

为了方便管理,SGI第二级分配器会主动将任何小额区块的内存需求量上调至8的倍数(如客端要求30字节,就自动调整为32个字节),并维护16个free-lists,各自管理大小为别为8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128字节的小额区块,free-lists的示意图如下:

  (图片来自于侯捷老师的课程《内存管理》ppt,侵删)

  比如我们申请32字节的空间,然后32 / 8 = 4,即应该落在3号的位置上。alloc内部并不是一次只申请这么多空间。而是一次申请需求的40倍那么大,即40 * 32 = 1280个字节。然后一半存进内存池,另一半切分为20小块, 分一块给客户,剩下的挂在5号元素上。比如再需要申请64个字节,64 / 8 = 8,挂在7号元素上,此时内存池有上次留下的1280 / 2 = 640个字节的空间. 640 / 64 = 10块,分一块给客户,剩下的挂在7号元素上。如图:

  假如当时内存池空间不足时,则再申请 64 * 40 = 2560个字节的空间. 其中一半1280个字节的空间存内存池,剩下的另一半切20个小块,一块分客户,剩下的挂7号元素上面。

  基于这样的原理: 每次申请一大块,慢慢切割来使用,可以减小cookie的不必要的浪费。想象一下,如果申请100万个小额空间,那么省下近800万个字节的空间。也不算小数目了。可谓为了内存利用率,无所不用其极。

然而现在G4.9版本已经不将alloc设置为默认分配器了,原因呢也不清楚。 当然了,这个alloc分配器还是存在的,毕竟这么好的东西。现在它已经在G4.9版本中换了个名字:_pool_alloc(就是内存池的意思嘛),而且也将它置于__gnu_cxx命名空间中,要是我们想用它来当做容器的分配器呢,可以这么使用:

    vector<int, __gnu_cxx::_pool_alloc<int>>   vec;

  当然了alloc内存格局还是非常复杂的,这里我们只是简单了解下它的基本原理。如需了解详情,推荐《STL源码剖析》。相关知识点于第二章---空间置配器(allocator)。

简单来谈谈alloc分配器的更多相关文章

  1. 【bzoj1604】【[Usaco2008 Open]Cow Neighborhoods】简单的谈谈曼哈顿距离

    (最近p站上不去要死了) Description 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个"群".每只奶牛在吃 ...

  2. G++ 4.4.7 无法编译模板程序,Vs可以,和解?智者尾部留言,本人第一次使用vs pro,通常并且习惯在linux下写些小东西,虽然程序简单;

    vs 模板编译运行Ok \ linux g++ 4.4.7编译模板测试程序,报无法定义 template <typename or class 中的 AnyType> 类型的数据 Exam ...

  3. iOS面试题汇总

    摘要:1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承;可以实现多个接口,通 ...

  4. 最全的iOS面试题及答案-转载

    1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承:可以实现多个接口,通过实现 ...

  5. 李洪强iOS经典面试题124

    1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承;可以实现多个接口,通过实现 ...

  6. 超全!iOS 面试题汇总

    之前看了很多面试题,感觉要不是不够就是过于冗余,于是我将网上的一些面试题进行了删减和重排,现在分享给大家.(题目来源于网络,侵删) 1. Object-c的类可以多重继承么?可以实现多个接口么?Cat ...

  7. iOS面试题及答案2015.6.7

    iOS面试题及答案     1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承 ...

  8. linux设备驱动归纳总结(三):6.poll和sellct【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-61749.html linux设备驱动归纳总结(三):6.poll和sellct xxxxxxxxxx ...

  9. iOS 面试题汇总

    1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承;可以实现多个接口,通过实现 ...

随机推荐

  1. cookie窃取和session劫持

    Updates 2014-08-17 感谢@搞前端的crosser的提醒,加入了HTTP Response Splitting的内容. 此篇文章的Presentation戳这里. 一.cookie的基 ...

  2. 团队开发——冲刺1.e

    冲刺阶段一(第五天) 冲刺阶段一(第五天) 1.昨天做了什么?优化界面细节. 查看C#资料,再解决自己电脑的问题. 2.今天准备做什么? 为解决自己电脑的问题,查找关于C#的资料,后期做准备.

  3. 关于PCA的几何表示——MATLAB实现

    关于PCA的一道练习题.这个折腾了好久...终于做出来像样的图,开始的时候忘记对原始数据标准化,怎么也不对.经过标准化之后,做的图看着还可以,有错误请指出! MATLAB代码PCA.m: clear ...

  4. Python OpenCV —— Modifying

    一些索引和修改图像像素点数据等的操作,可打印观察运行结果. # -*- coding: utf-8 -*- """ Created on Wed Sep 28 00:11 ...

  5. join()、implode()函数

    join() 函数 join() 函数把数组元素组合为一个字符串. join() 函数是 implode() 函数的别名. 语法 join(separator,array) 参数 描述 separat ...

  6. Linux下手动获取当前调用栈

    被问到如何手动获取当前的调用栈,之前碰到过一时没记起来,现在回头整理一下. 其原理是:使用backtrace()从栈中获取当前调用各层函数调用的返回地址,backtrace_symbols()将对应地 ...

  7. Codeforces Round #164 (Div. 2)

    A. Games 模拟. B. Buttons 简单计数. C. Beautiful Sets of Points 显然每行每列只能有一个点,那么最大点数为\(1+min(n, m)\). 在不考虑\ ...

  8. word转pdf字体格式变乱的问题

    完成word转pdf的功能之后,本地测试没问题,然后发布到服务器上,就遇到了字体变乱的问题,如下: 由于我本地发布后导出没有出现同样情况,而服务器和本地的最大区别在于字体库,于是,把服务器上关于需要用 ...

  9. POJ-3261 Milk Patterns(后缀数组)

    题目大意:找出至少出现K次的子串的最长长度. 题目分析:二分枚举长度x,判断有没有最长公共前缀不小于x的并且连续出现了至少k次的有序子串区间. 代码如下: # include<iostream& ...

  10. SSD(Single Shot MultiBox Detector)的安装配置和运行

    下文图文介绍转自watersink的博文SSD(Single Shot MultiBox Detector)不得不说的那些事. 该方法出自2016年的一篇ECCV的oral paper,SSD: Si ...