Chinaunix首页 | 论坛 | 博客
  • 博客访问: 259011
  • 博文数量: 21
  • 博客积分: 1263
  • 博客等级: 准尉
  • 技术积分: 697
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-24 00:05
个人简介

专注于Answers Ranking, Answer Monitor和log处理。

文章分类
文章存档

2014年(5)

2012年(16)

分类: C/C++

2012-04-10 15:10:03

STL里面将内存分配按照两类来分配,一种是不大于128bytes的,是通过内存池管理的,一种是大于128bytes就直接通过malloc/realloc分配的。因为现在主要根据《STL源码剖析》一书来看。所以我们也先看看这个alloc的接口:

  1. template<class _Tp, class _Alloc>
  2. class simple_alloc {

  3. public:
  4.     static _Tp* allocate(size_t __n)
  5.       { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }
  6.     static _Tp* allocate(void)
  7.       { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); }
  8.     static void deallocate(_Tp* __p, size_t __n)
  9.       { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); }
  10.     static void deallocate(_Tp* __p)
  11.       { _Alloc::deallocate(__p, sizeof (_Tp)); }
  12. };

可以看到是根据第二个类型参数_Alloc调用它的static函数来完成内存分配的。其实主要就是用的
template class __default_alloc_template 和
template class __malloc_alloc_template 来分配内存的。
先看看__malloc_alloc_template代码,因为它要比较简单一些:


  1. template <int __inst>
  2. class __malloc_alloc_template {

  3. private:

  4.   static void* _S_oom_malloc(size_t);
  5.   static void* _S_oom_realloc(void*, size_t);

  6. #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
  7.   static void (* __malloc_alloc_oom_handler)();
  8. #endif

  9. public:

  10.   static void* allocate(size_t __n)
  11.   {
  12.     void* __result = malloc(__n);
  13.     if (0 == __result) __result = _S_oom_malloc(__n);
  14.     return __result;
  15.   }

  16.   static void deallocate(void* __p, size_t /* __n */)
  17.   {
  18.     free(__p);
  19.   }

  20.   static void* reallocate(void* __p, size_t /* old_sz */, size_t __new_sz)
  21.   {
  22.     void* __result = realloc(__p, __new_sz);
  23.     if (0 == __result) __result = _S_oom_realloc(__p, __new_sz);
  24.     return __result;
  25.   }

  26.   static void (* __set_malloc_handler(void (*__f)()))()
  27.   {
  28.     void (* __old)() = __malloc_alloc_oom_handler;
  29.     __malloc_alloc_oom_handler = __f;
  30.     return(__old);
  31.   }

  32. };

  33. // malloc_alloc out-of-memory handling

  34. #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
  35. template <int __inst>
  36. void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0;
  37. #endif

  38. template <int __inst>
  39. void*
  40. __malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n)
  41. {
  42.     void (* __my_malloc_handler)();
  43.     void* __result;

  44.     for (;;) {
  45.         __my_malloc_handler = __malloc_alloc_oom_handler;
  46.         if (0 == __my_malloc_handler) { __THROW_BAD_ALLOC; }
  47.         (*__my_malloc_handler)();
  48.         __result = malloc(__n);
  49.         if (__result) return(__result);
  50.     }
  51. }

  52. template <int __inst>
  53. void* __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p, size_t __n)
  54. {
  55.     void (* __my_malloc_handler)();
  56.     void* __result;

  57.     for (;;) {
  58.         __my_malloc_handler = __malloc_alloc_oom_handler;
  59.         if (0 == __my_malloc_handler) { __THROW_BAD_ALLOC; }
  60.         (*__my_malloc_handler)();
  61.         __result = realloc(__p, __n);
  62.         if (__result) return(__result);
  63.     }
  64. }

allocate/reallocate就是分配内存的函数了,它调用malloc/realloc进行分配,如果不成功就调用
_S_oom_malloc/S_oom_realloc(oom应该就是out of memory的意思)函数重新进行分配,但是它有一个前提就是设置了初始给函数指针__malloc_alloc_oom_handler赋了值。默认的动作是__THROW_BAD_ALLOC

  1. #ifndef __THROW_BAD_ALLOC
  2. # if defined(__STL_NO_BAD_ALLOC) || !defined(__STL_USE_EXCEPTIONS)
  3. # include <stdio.h>
  4. # include <stdlib.h>
  5. # define __THROW_BAD_ALLOC fprintf(stderr, "out of memory\n"); exit(1)
  6. # else /* Standard conforming out-of-memory handling */
  7. # include <new>
  8. # define __THROW_BAD_ALLOC throw std::bad_alloc()
  9. # endif
  10. #endif
即它或是打印一个错误信息并退出或是抛出一个bad_alloc异常。

static void (* __set_malloc_handler(void (*__f)()))() 就是设置__malloc_alloc_oo
m_handler指针的函数,它看起来比较复杂,其实分析出来就是它的参数和返回值都是一个不接收任何参数并且返回值为void的函数指针。通过它给_malloc_alloc_oom_handler赋值,遇到malloc/realloc分配失败的时候就会先执行这个函数,并重新尝试分配(当然前提是函数没有退出……)
阅读(2269) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~