一级配置器

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 一级配置器
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. 因为处理函数会跟后面的内存不足有关系

1
2
3
4
5
6
// 这里是模仿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, 只有用户自己设置

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

allocate

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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释放内存

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

reallocate

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

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

1
2
3
4
5
6
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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函数, 并且设置统一的调用接口, 默认的的接口为第二级配置器

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

统一的接口

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 定义符合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对malloc和free用函数重新进行了封装, 同时一级还是二级都做了统一的接口. 接下来我们继续分析第二级配置器.