前言

上一节我们分析了空间配置器对new的配置, 而STL将空间配置器分为了两级, 第一级是直接调用malloc分配空间, 调用free释放空间, 第二级三就是建立一个内存池, 小于128字节的申请都直接在内存池申请, 不直接调用mallocfree.

本节我们就先分析第一种空间配置器, 直接调用malloc, free, 而STL有是怎样的封装处理.

一级配置器

一级配置器的类. 它无template型别参数. 这里我将public定义的函数和私有成员函数成对分离出来讲解.

// 一级配置器
template <int inst>
class __malloc_alloc_template
{
// 这里private里面的函数都是在内存不足的时候进行调用的
private:
static void *oom_malloc(size_t); // 分配不足
static void *oom_realloc(void *, size_t); // 重新分配不足
#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
static void (* __malloc_alloc_oom_handler)(); // 内存不足设置的处理例程, 默认设置的是0, 表示没有设置处理例程, 这个处理例程是由用户手动设置的
#endif
public:
};

唯一比较麻烦的就是set_malloc_handler 它就是接受一个函数指针, 用来保存用户自定义的处理函数, 如果用户没有设置的话, 默认就设置为0. 因为处理函数会跟后面的内存不足有关系.

// 这里是模仿c++的set_new_handler. 是由用户自己定义的处理函数, 没有设置默认为0
static void (* set_malloc_handler(void (*f)()))()
{
void (* old)() = __malloc_alloc_oom_handler;
__malloc_alloc_oom_handler = f;
return(old);
}

默认将处理例程设置为0, 只有用户自己设置.

template <int inst>
void (* __malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;

allocate

allocate : 很明显, 这里直接调用malloc分配内存, 当内存不足的时候, 程序继续调用oom_malloc来选择抛出异常还是一直申请内存, 直到申请内存成功.

// 在分配和再次分配中, 都会检查内存不足, 在不足的时候直接调用private中相应的函数
static void * allocate(size_t n)
{
void *result = malloc(n);
if (0 == result) result = oom_malloc(n);
return result;
}

oom_malloc函数功能 : 除非用户自定义了处理例程, 否则当内存不足的时候直接输出内存不足的提示然后直接调用exit(1);

用户定义了处理程序, 函数会一直进行内存申请, 直到申请到内存为止

template <int inst>
void * __malloc_alloc_template<inst>::oom_malloc(size_t n)
{
void (* my_malloc_handler)();
void *result;
// 用户自定义处理例程, 就一直申请内存, 否则抛出异常
for (;;)
{
my_malloc_handler = __malloc_alloc_oom_handler;
if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }
(*my_malloc_handler)();
result = malloc(n);
if (result) return(result);
}
}

deallocate

一级配置器直接调用free释放内存

static void deallocate(void *p, size_t /* n */)
{
free(p);
}

reallocate

下面的函数都是很简单的或是重复的功能, 就一笔带过.

这里reallocate和oom_realloc和上面allocate一样的, 这里就不做过多的解释了.

static void * reallocate(void *p, size_t /* old_sz */, size_t new_sz)
{
void * result = realloc(p, new_sz);
if (0 == result) result = oom_realloc(p, new_sz);
return result;
}
template <int inst>
void * __malloc_alloc_template<inst>::oom_realloc(void *p, size_t n)
{
void (* my_malloc_handler)();
void *result; for (;;) {
my_malloc_handler = __malloc_alloc_oom_handler;
if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }
(*my_malloc_handler)();
result = realloc(p, n);
if (result) return(result);
}
}

程序默认定义mallo_alloc函数, 并且设置统一的调用接口, 默认的的接口为第二级配置器

// 默认将malloc_alloc设为0;
typedef __malloc_alloc_template<0> malloc_alloc;

统一的接口

定义符合STL规格的配置器接口, 不管是一级配置器还是二级配置器都是使用这个接口进行分配的

// 定义符合STL规格的配置器接口, 不管是一级配置器还是二级配置器都是使用这个接口进行分配的
template<class T, class Alloc>
class simple_alloc {
public:
static T *allocate(size_t n)
{ return 0 == n? 0 : (T*) Alloc::allocate(n * sizeof (T)); }
static T *allocate(void)
{ return (T*) Alloc::allocate(sizeof (T)); }
static void deallocate(T *p, size_t n)
{ if (0 != n) Alloc::deallocate(p, n * sizeof (T)); }
static void deallocate(T *p)
{ Alloc::deallocate(p, sizeof (T)); }
};

总结

本节对STL的第一级配置器做了分析, STL对malloc和free用函数重新进行了封装, 同时一级还是二级都做了统一的接口. 接下来我们继续分析第二级配置器.

STL源码分析之第一级配置器的更多相关文章

  1. STL源码分析之第二级配置器

    前言 第一级是直接调用malloc分配空间, 调用free释放空间, 第二级三就是建立一个内存池, 小于128字节的申请都直接在内存池申请, 不直接调用malloc和free. 本节分析第二级空间配置 ...

  2. 《STL源码剖析》chapter2空间配置器allocator

    为什么不说allocator是内存配置器而说是空间配置器,因为空间不一定是内存,也可以是磁盘或其他辅助介质.是的,你可以写一个allocator,直接向硬盘取空间.sgi stl提供的配置器,配置的对 ...

  3. STL源码分析读书笔记--第二章--空间配置器(allocator)

    声明:侯捷先生的STL源码剖析第二章个人感觉讲得蛮乱的,而且跟第三章有关,建议看完第三章再看第二章,网上有人上传了一篇读书笔记,觉得这个读书笔记的内容和编排还不错,我的这篇总结基本就延续了该读书笔记的 ...

  4. 《STL源码剖析》——第一、二、三章

     第一章:概论: 换句话说,STL所实现的,是依据泛型思维架设起来的一个概念结构.这个以抽象概念(abstract concepts)为主体而非以实际类(classes)为主体的结构,形成了一个严谨的 ...

  5. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  6. STL源码分析《4》----Traits技术

    在 STL 源码中,到处可见 Traits 的身影,其实 Traits 不是一种语法,更确切地说是一种技术. STL库中,有一个函数叫做 advance, 用来将某个迭代器(具有指针行为的一种 cla ...

  7. STL源码分析《3》----辅助空间不足时,如何进行归并排序

    两个连在一起的序列 [first, middle) 和 [middle, last) 都已经排序, 归并排序最核心的算法就是 将 [first, middle) 和 [middle, last) 在  ...

  8. STL 源码分析《1》---- list 归并排序的 迭代版本, 神奇的 STL list sort

    最近在看 侯捷的 STL源码分析,发现了以下的这个list 排序算法,乍眼看去,实在难以看出它是归并排序. 平常大家写归并排序,通常写的是 递归版本..为了效率的考虑,STL库 给出了如下的 归并排序 ...

  9. STL——空间的配置和释放std::alloc(第一级配置器和第二级配置器)

    1 空间的配置和释放,std::alloc 对象构造前的空间配置和对象析构后的空间释放,由<stl_alloc.h>负责,SGI对此的设计哲学如下: 向system heap要求空间 考虑 ...

随机推荐

  1. oc28--Property增强

    // // Person.h #import <Foundation/Foundation.h> @interface Person : NSObject /* { @public int ...

  2. tflearn中num_epoch含义就是针对所有样本的一次迭代

    In tensorflow get started code: import tensorflow as tf import numpy as np features = [tf.contrib.la ...

  3. 【BZOJ 1598】 牛跑步

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1598 [算法] A*求k短路 [代码] #include<bits/stdc+ ...

  4. 使用 Polyfill 而不再是 bable 来实践js新特性

    现状 我们想要用ES6 语法来写 JavaScript.然而由于我们需要兼容老版本的浏览器,那些浏览器不支持 ES6,我们需要解决这个问题. 有一个标准的做法是:写 ES6 代码 → 将所有代码编译成 ...

  5. js软键盘

    <<!DOCTYPE html><html><head>  <title></title></head><body& ...

  6. [Apple开发者帐户帮助]三、创建证书(5)创建WatchKit服务证书

    WatchKit服务证书允许您使用Apple推送通知(APN)将更新推送到Apple Watch上的复杂功能. 所需角色:帐户持有人或管理员. 在证书,标识符和配置文件中,从左侧的弹出菜单中选择iOS ...

  7. DCOM 找不到 office word 的解决方法

    1. 在运行里面  输入     comexp.msc -32  2.在“DCOM配置”中,为IIS账号配置操作Word(其他Office对象也一样)的权限. 具体操作:“组件服务(Component ...

  8. [转]利用 NPOI 變更字體尺寸及樣式

    本文转自:http://blog.cscworm.net/?p=1650 利用 NPOI 變更字體尺寸及樣式: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ...

  9. centOS 7.4 安装配置jdk1.8

    按以下步骤安装 JDK. 1.新建一个目录: mkdir /usr/java 2.通过XShell 上传本地安装包或者通过命令下载在线安装包 wget http://mirrors.linuxeye. ...

  10. Spring Boot (2) Restful风格接口

    Rest接口 动态页面jsp早已过时,现在流行的是vuejs.angularjs.react等前端框架 调用 rest接口(json格式),如果是单台服务器,用动态还是静态页面可能没什么大区别,如果服 ...