1.原理介绍:
SGI STL第一级配置器采用的:
1.allocate()
直接调用malloc
或者reallocate()
直接调用realloc
deallocate()
直接使用free
2.模拟C++的set_new_handler
机制以处理内存不足的情况,:当调用
allocate()
未分配到内存时,会调用oom_mallc()
,它会不断尝试释放,配置,再释放,再配置,处理”内存不足”交给客端(取决于客端如何编写),也就是,需要客端定义__malloc_alloc_oom_handler
处理函数,在调用allocate/reallocate
之前注册set_malloc_handler
函数的事件(即__malloc_alloc_oom_handler函数)即可
这些源码中体现明确,以下是源码
#if 0
# include <new>
# define __THROW_BAD_ALLOC throw bad_alloc
#elif !defined(__THROW_BAD_ALLOC)
# include <iostream>
# include <stdlib.h>
#define __THROW_BAD_ALLOC std::cerr<<"out of memory"<<std::endl; exit(1)
#endif
//第一级空间配置器
template<int inst>
class __malloc_alloc_template
{
private:
//处理内存不足的情况
//oom: out of memory
static void *oom_malloc(size_t);
static void *oom_realloc(void *, size_t);
static void (* __malloc_alloc_oom_handler)();
public:
static void * allocate(size_t n)
{
void *result = malloc(n); //第一级配置器直接使用malloc()
//无法满足需求时,直接使用oom_malloc()
if(0 == result)
result = oom_malloc(n);
return result;
}
static void deallocate(void *p, size_t )
{
free(p);
}
static void *reallocate(void *p, size_t , size_t new_sz)
{
void * result = realloc(p, new_sz);
if(0 == result)
result = oom_realloc(p, new_sz);
return result;
}
static void (*set_malloc_handler(void (*f)()))()//函数返回值为函数指针,参数是函数指针
{
void (*old)() = __malloc_alloc_oom_handler;
__malloc_alloc_oom_handler = f;
return (old);
}
};
//malloc_alloc out_of_memory handling
template<int inst>
void (*__malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;
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;
}
}
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;
}
}
typedef __malloc_alloc_template<0> malloc_alloc;
2.源码测试
(1)不注册__malloc_alloc_oom_handler
函数
#include <iostream>
#include "stl_malloc.h"
using namespace std;
int main()
{
void * p = __malloc_alloc_template<0>::allocate(64424509440);
__malloc_alloc_template<0>::deallocate(p, 0);
}
结果:
[root@server10 stl_alloc]# make
g++ stl_main.cpp -o main
[root@server10 stl_alloc]# ./main
out of memory
(2)注册一个简单的__malloc_alloc_oom_handler
函数
[root@server10 stl_alloc]# make
g++ stl_main.cpp -o main
[root@server10 stl_alloc]# ./main
This is oom function
set_malloc_handler模拟了一个回调函数,参数是函数的地址,关于回调函数的介绍可以参考https://www.zhihu.com/compatibility/index.html