STL内存创建

Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu  转载请标明来源

1.      Stl内存创建基类模板__malloc_alloc_template

STL的经常使用的内存创建參考文件: stl_alloc.h,文件里定义了__malloc_alloc_template模板库,创建与释放使用C方法malloc、free、realloc,模板库里面主要对外提供了函数:

allocate: 分配内存

deallocate: 释放内存

reallocate: 又一次分配内存

__set_malloc_handler:
设置异常处理函数

template <int __inst>

class __malloc_alloc_template {

private:

static void* _S_oom_malloc(size_t);

static void* _S_oom_realloc(void*, size_t);

#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG

static void (* __malloc_alloc_oom_handler)();

#endif

public:

static void* allocate(size_t __n)

{

void* __result = malloc(__n);

if (0 == __result) __result = _S_oom_malloc(__n);

return __result;

}

static void deallocate(void* __p, size_t /* __n */)

{

free(__p);

}

static void* reallocate(void* __p, size_t /* old_sz */, size_t __new_sz)

{

void* __result = realloc(__p, __new_sz);

if (0 == __result) __result = _S_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);

}

};

2.   内存分配与释放

使用malloc和realloc分配内存,对于分配内存异常的处理,模板库中交给内部的这两个静态方法:

_S_oom_malloc

_S_oom_ realloc

使用free释放内存,对于释放内存来说,是无异常处理的,直接调用free指针,传入的size_t未使用。

3   分配异常处理

分配内存的异常处理方法,參考_S_oom_malloc/_S_oom_realloc中的实现

在实现中或者是通过抛出异常,或者是通过运行约定的处理函数(如内存整理函数),然后继续申请内存。

在以下的函数中,涉及了函数指针:

__malloc_alloc_oom_handler

这个函数指定方法__malloc_alloc_template ::__set_malloc_handler

假设这个函数未指定的话,调用异常__THROW_BAD_ALLOC处理

a.   C++下,抛出std::bad_alloc(),

b.   C下,向标准输出中打印并终止程序: fprintf(stderr, "out of memory\n"); exit(1)

假设这个函数指定的话,指行这个函数(比如内存整理函数),然后再次申请内存,直到成功申请到后返回申请到的内存地址:

__my_malloc_handler = __malloc_alloc_oom_handler;

(*__my_malloc_handler)();

__result = malloc(__n);

if (__result) return(__result);

#ifndef __THROW_BAD_ALLOC

#  if defined(__STL_NO_BAD_ALLOC) || !defined(__STL_USE_EXCEPTIONS)

#    include <stdio.h>

#    include <stdlib.h>

#    define __THROW_BAD_ALLOC fprintf(stderr, "out of memory\n"); exit(1)

#  else /* Standard conforming out-of-memory handling */

#    include <new>

#    define __THROW_BAD_ALLOC throw std::bad_alloc()

#  endif

#endif

#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG

template <int __inst>

void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0;

#endif

template <int __inst>

void*

__malloc_alloc_template<__inst>::_S_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>::_S_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);

}

}

4.   封装的几组分配方式

a.   Simple_alloc,附加了检查0/NULL的操作

template<class _Tp, class _Alloc>

class simple_alloc {

public:

static _Tp* allocate(size_t __n)

{ return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }

static _Tp* allocate(void)

{ return (_Tp*) _Alloc::allocate(sizeof (_Tp)); }

static void deallocate(_Tp* __p, size_t __n)

{ if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); }

static void deallocate(_Tp* __p)

{ _Alloc::deallocate(__p, sizeof (_Tp)); }

};

b.   debug_alloc每次分配时,多附加8字节的空间,用于存储当前分配的size大小。

// Allocator adaptor to check size arguments for debugging.

// Reports errors using assert.  Checking can be disabled with

// NDEBUG, but it's far better to just use the underlying allocator

// instead when no checking is desired.

// There is some evidence that this can confuse Purify.

template <class _Alloc>

class debug_alloc {

private:

enum {_S_extra = 8};  // Size of space used to store size.  Note

// that this must be large enough to preserve

// alignment.

public:

static void* allocate(size_t __n)

{

char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra);

*(size_t*)__result = __n;

return __result + (int) _S_extra;

}

static void deallocate(void* __p, size_t __n)

{

char* __real_p = (char*)__p - (int) _S_extra;

assert(*(size_t*)__real_p == __n);

_Alloc::deallocate(__real_p, __n + (int) _S_extra);

}

static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz)

{

char* __real_p = (char*)__p - (int) _S_extra;

assert(*(size_t*)__real_p == __old_sz);

char* __result = (char*)

_Alloc::reallocate(__real_p, __old_sz + (int) _S_extra,

__new_sz + (int) _S_extra);

*(size_t*)__result = __new_sz;

return __result + (int) _S_extra;

}

};

5.   内存分配类allocator/__allocator

allocator分配类使用缺省的分配类(alloc),使用分配类的静态方法。

__allocator类须要输入分配类,并对分配类实例化了对像,调用对像的分配方法分配内存。

a)   allocator

// This implements allocators as specified in the C++ standard.

//

// Note that standard-conforming allocators use many language features

// that are not yet widely implemented.  In particular, they rely on

// member templates, partial specialization, partial ordering of function

// templates, the typename keyword, and the use of the template keyword

// to refer to a template member of a dependent type.

#ifdef __STL_USE_STD_ALLOCATORS

template <class _Tp>

class allocator {

typedef alloc _Alloc;          // The underlying allocator.

public:

typedef size_t     size_type;

typedef ptrdiff_t  difference_type;

typedef _Tp*       pointer;

typedef const _Tp* const_pointer;

typedef _Tp&       reference;

typedef const _Tp& const_reference;

typedef _Tp        value_type;

template <class _Tp1> struct rebind {

typedef allocator<_Tp1> other;

};

allocator() __STL_NOTHROW {}

allocator(const allocator&) __STL_NOTHROW {}

template <class _Tp1> allocator(const allocator<_Tp1>&) __STL_NOTHROW {}

~allocator() __STL_NOTHROW {}

pointer address(reference __x) const { return &__x; }

const_pointer address(const_reference __x) const { return &__x; }

// __n is permitted to be 0.  The C++ standard says nothing about what

// the return value is when __n == 0.

_Tp* allocate(size_type __n, const void* = 0) {

return __n != 0 ? static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp)))

: 0;

}

// __p is not permitted to be a null pointer.

void deallocate(pointer __p, size_type __n)

{ _Alloc::deallocate(__p, __n * sizeof(_Tp)); }

size_type max_size() const __STL_NOTHROW

{ return size_t(-1) / sizeof(_Tp); }

void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }

void destroy(pointer __p) { __p->~_Tp(); }

};

 

b)   __allocator

能够传入不同的分配方式,另外实例化了对像,支持对象内记录分配字节等,属于对复杂分配方式的支的。

__allocator最大的特点,实例化了分配对像

// Allocator adaptor to turn an SGI-style allocator (e.g. alloc, malloc_alloc)

// into a standard-conforming allocator.   Note that this adaptor does

// *not* assume that all objects of the underlying alloc class are

// identical, nor does it assume that all of the underlying alloc's

// member functions are static member functions.  Note, also, that

// __allocator<_Tp, alloc> is essentially the same thing as allocator<_Tp>.

template <class _Tp, class _Alloc>

struct __allocator {

_Alloc __underlying_alloc;

typedef size_t    size_type;

typedef ptrdiff_t difference_type;

typedef _Tp*       pointer;

typedef const _Tp* const_pointer;

typedef _Tp&       reference;

typedef const _Tp& const_reference;

typedef _Tp        value_type;

template <class _Tp1> struct rebind {

typedef __allocator<_Tp1, _Alloc> other;

};

__allocator() __STL_NOTHROW {}

__allocator(const __allocator& __a) __STL_NOTHROW

: __underlying_alloc(__a.__underlying_alloc) {}

template <class _Tp1>

__allocator(const __allocator<_Tp1, _Alloc>& __a) __STL_NOTHROW

: __underlying_alloc(__a.__underlying_alloc) {}

~__allocator() __STL_NOTHROW {}

pointer address(reference __x) const { return &__x; }

const_pointer address(const_reference __x) const { return &__x; }

// __n is permitted to be 0.

_Tp* allocate(size_type __n, const void* = 0) {

return __n != 0

? static_cast<_Tp*>(__underlying_alloc.allocate(__n * sizeof(_Tp)))

: 0;

}

// __p is not permitted to be a null pointer.

void deallocate(pointer __p, size_type __n)

{ __underlying_alloc.deallocate(__p, __n * sizeof(_Tp)); }

size_type max_size() const __STL_NOTHROW

{ return size_t(-1) / sizeof(_Tp); }

void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }

void destroy(pointer __p) { __p->~_Tp(); }

};

6.   内存分配结构体

这个结构体非常有意思,

參数一: _S_instanceless标识包括有allocator_type定义

參数二: _Alloc_type,简单分配方式,simple_alloc调用_Alloc的静态方法进行分配释放内存

參数三:  allocator_type,可支持复杂分配方式,实例化了_Alloc对像,使用对象方法分配释放内存,支持对象内包括分配的总数,或其他附加信息,能够在对像内实现内存池等。

template <class _Tp, class _Alloc>

struct _Alloc_traits<_Tp, debug_alloc<_Alloc> >

{

static const bool _S_instanceless = true;

typedef simple_alloc<_Tp, debug_alloc<_Alloc> > _Alloc_type;

typedef __allocator<_Tp, debug_alloc<_Alloc> > allocator_type;

};

STL内存分配的更多相关文章

  1. STL内存分配方式

    关于STL用的很多比如map, vector, set, queue, stack等等.很少关注它的内存分配情况,但是经常遇到比如使用map,不停的在map中插入了一些很小的对象,然后释放了一些,然后 ...

  2. SGI STL 内存分配方式及malloc底层实现分析

    在STL中考虑到小型区块所可能造成的内存碎片问题,SGI STL设计了双层级配置器,第一级配置器直接使用malloc()和free();第二级配置器则视情况采用不同的策略:当配置区块超过128byte ...

  3. C++STL内存管理方法(g++版)

    STL作为C++的经典作品,一直备受人们关注.本文主要介绍STL的内存管理策略. 早期的STL内存管理 第一次接触STL源码是看侯捷先生的<STL源码剖析>,此书通俗易懂,剖析透彻,是极佳 ...

  4. C++ STL vector 内存分配

    vector为了支持快速的随机访问,vector容器的元素以连续方式存放,每一个元素都紧挨着前一个元素存储. 当vector添加一个元素时,为了满足连续存放这个特性,都需要重新分配空间.拷贝元素.撤销 ...

  5. STL六大组件之——分配器(内存分配,好深奥的东西)

    SGI设计了双层级配置器,第一级配置器直接使用malloc()和free(),第二级配置器则视情况采用不同的策略:当配置区块超过128bytes时,视之为“足够大”,便调用第一级配置器:当配置区小于1 ...

  6. STL容器的内存分配

    这篇文章参考的是侯捷的<STL源码剖析>,所以主要介绍的是SGI STL实现版本,这个版本也是g++自带的版本,另外有J.Plauger实现版本对应的是cl自带的版本,他们都是基于HP实现 ...

  7. STL内存管理器的分配策略

    STL提供了很多泛型容器,如vector,list和map.程序员在使用这些容器时只需关心何时往容器内塞对象,而不用关心如何管理内存,需要用多少内存,这些STL容器极大地方便了C++程序的编写.例如可 ...

  8. 解析STL中典型的内存分配

    1 vector 在C++中使用vector应该是非常频繁的,但是你是否知道vector在计算内存分配是如何么? 在c++中vector是非常类似数组,但是他比数组更加灵活,这就表现在他的大小是可以自 ...

  9. (转)C++ STL中的vector的内存分配与释放

    C++ STL中的vector的内存分配与释放http://www.cnblogs.com/biyeymyhjob/archive/2012/09/12/2674004.html 1.vector的内 ...

随机推荐

  1. VSTO之旅系列(四):创建Word解决方案

    原文:VSTO之旅系列(四):创建Word解决方案 本专题概要 引言 Word对象模型 创建Word外接程序 小结 一.引言 在上一个专题中主要为大家介绍如何自定义我们的Excel 界面的,然而在这个 ...

  2. Matlab---串口操作---数据採集篇

    matlab功能强大,串口操作也非常easy.相信看过下面两个实验你就能掌握咯! 開始吧! 实验1: 从电脑COM2口读取数据.并将数据保存在TXT文件里,方便数据分析,以下是M脚本: %名 称:Ma ...

  3. 鸟哥Linux私房菜知识点总结6到7章

    近期翻看了一本<鸟哥的Linux私房菜>.这是一本基础的书,万丈高楼平地起.会的不多但能够学.这是我整理的一些知识点.尽管非常基础.希望和大家共同交流. 第6章主机规划与磁盘分区 1.在进 ...

  4. sql server2012附加的数据库问题

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjM2NzUxMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  5. 完整导出IntelliJ IDEA的快捷键

    工欲善其事,必先利其器. 常常和代码打交道的人,熟练使用IDE快捷键那是必须的,由于快捷键能够把你从各种罗嗦事中解放出来.比方,假设没有快捷键,你就须要常常性的暂停快速执行的大脑,右手凭记忆摸到鼠标, ...

  6. Android基于发展Service音乐播放器

    这是一个基于Service组件的音乐播放器,程序的音乐将会由后台的Service组件负责播放,当后台的播放状态改变时,程序将会通过发送广播通知前台Activity更新界面:当用户单击前台Activit ...

  7. hdu2861(递推)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2861 题意:n个板凳有m个人坐,求刚好将序列分成k段的方式. 分析: a[n][m][k]=a[n-1 ...

  8. NYOJ 284 坦克大战 【BFS】+【优先队列】

    坦克大战 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描写叙述 Many of us had played the game "Battle city" ...

  9. MD5加密算法的实现

    //////////////////////////////////////////////////////////////////// /*                 md5.h        ...

  10. poj 3265 Problem Solving dp

    这个题目容易让人误以为是贪心就可以解决了,但是细想一下很容易举出反例. dp[i][j]表示解决了i个问题,最后一个月解决的问题数目. #include <iostream> #inclu ...