- enum {_ALIGN = 8};
- enum {_MAX_BYTES = 128};
- enum {_NFREELISTS = 16}; // _MAX_BYTES/_ALIGN
分配小内存是通过己申请的内存进行分配的,它通过16(_NFREELISTS)个链表来管理申请的内存。而且分配的倍数是8(_ALIGN)的倍数,就算你申请1byte它也会给你分配8byte。16*8=128(_MAX_BYTES)。所以可以看到这16个链表节点分别是大小为8,16,24,... ... ,128bytes.
- union _Obj {
- union _Obj* _M_free_list_link;
- char _M_client_data[1]; /* The client sees this. */
- };
- template <bool __threads, int __inst>
- char* __default_alloc_template<__threads, __inst>::_S_start_free = 0;
- template <bool __threads, int __inst>
- char* __default_alloc_template<__threads, __inst>::_S_end_free = 0;
- template <bool __threads, int __inst>
- size_t __default_alloc_template<__threads, __inst>::_S_heap_size = 0;
- template <bool __threads, int __inst>
- typename __default_alloc_template<__threads, __inst>::_Obj* __STL_VOLATILE
- __default_alloc_template<__threads, __inst> ::_S_free_list[
- # if defined(__SUNPRO_CC) || defined(__GNUC__) || defined(__HP_aCC)
- _NFREELISTS
- # else
- __default_alloc_template<__threads, __inst>::_NFREELISTS
- # endif
- ] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
- /* __n must be > 0 */
- static void* allocate(size_t __n)
- {
- void* __ret = 0;
- if (__n > (size_t) _MAX_BYTES) {
- __ret = malloc_alloc::allocate(__n);
- }
- else {
- _Obj* __STL_VOLATILE* __my_free_list
- = _S_free_list + _S_freelist_index(__n);
- // Acquire the lock here with a constructor call.
- // This ensures that it is released in exit or during stack
- // unwinding.
- # ifndef _NOTHREADS
- /*REFERENCED*/
- _Lock __lock_instance;
- # endif
- _Obj* __RESTRICT __result = *__my_free_list;
- if (__result == 0)
- __ret = _S_refill(_S_round_up(__n));
- else {
- *__my_free_list = __result -> _M_free_list_link;
- __ret = __result;
- }
- }
- return __ret;
- };
- typedef __malloc_alloc_template<0> malloc_alloc;
- static size_t _S_freelist_index(size_t __bytes) {
- return (((__bytes) + (size_t)_ALIGN-1)/(size_t)_ALIGN - 1);
- }
- static size_t
- _S_round_up(size_t __bytes)
- { return (((__bytes) + (size_t) _ALIGN-1) & ~((size_t) _ALIGN - 1)); }
- /* We allocate memory in large chunks in order to avoid fragmenting */
- /* the malloc heap too much. */
- /* We assume that size is properly aligned. */
- /* We hold the allocation lock. */
- template <bool __threads, int __inst>
- char*
- __default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size,
- int& __nobjs)
- {
- char* __result;
- size_t __total_bytes = __size * __nobjs;
- size_t __bytes_left = _S_end_free - _S_start_free;
- if (__bytes_left >= __total_bytes) {
- __result = _S_start_free;
- _S_start_free += __total_bytes;
- return(__result);
- } else if (__bytes_left >= __size) {
- __nobjs = (int)(__bytes_left/__size);
- __total_bytes = __size * __nobjs;
- __result = _S_start_free;
- _S_start_free += __total_bytes;
- return(__result);
- } else {
- size_t __bytes_to_get = 2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
- // Try to make use of the left-over piece.
- if (__bytes_left > 0) {
- _Obj* __STL_VOLATILE* __my_free_list = _S_free_list + _S_freelist_index(__bytes_left);
- ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
- *__my_free_list = (_Obj*)_S_start_free;
- }
- _S_start_free = (char*)malloc(__bytes_to_get);
- if (0 == _S_start_free) {
- size_t __i;
- _Obj* __STL_VOLATILE* __my_free_list;
- _Obj* __p;
- // Try to make do with what we have. That can't
- // hurt. We do not try smaller requests, since that tends
- // to result in disaster on multi-process machines.
- for (__i = __size;
- __i <= (size_t) _MAX_BYTES;
- __i += (size_t) _ALIGN) {
- __my_free_list = _S_free_list + _S_freelist_index(__i);
- __p = *__my_free_list;
- if (0 != __p) {
- *__my_free_list = __p -> _M_free_list_link;
- _S_start_free = (char*)__p;
- _S_end_free = _S_start_free + __i;
- return(_S_chunk_alloc(__size, __nobjs));
- // Any leftover piece will eventually make it to the
- // right free list.
- }
- }
- _S_end_free = 0; // In case of exception.
- _S_start_free = (char*)malloc_alloc::allocate(__bytes_to_get);
- // This should either throw an
- // exception or remedy the situation. Thus we assume it
- // succeeded.
- }
- _S_heap_size += __bytes_to_get;
- _S_end_free = _S_start_free + __bytes_to_get;
- return(_S_chunk_alloc(__size, __nobjs));
- }
- }
- _S_start_free = (char*)malloc_alloc::allocate(__bytes_to_get);
- template <bool __threads, int __inst>
- void*
- __default_alloc_template<__threads, __inst>::_S_refill(size_t __n)
- {
- int __nobjs = 20;
- char* __chunk = _S_chunk_alloc(__n, __nobjs);
- _Obj* __STL_VOLATILE* __my_free_list;
- _Obj* __result;
- _Obj* __current_obj;
- _Obj* __next_obj;
- int __i;
- if (1 == __nobjs) return(__chunk);
- __my_free_list = _S_free_list + _S_freelist_index(__n);
- /* Build free list in chunk */
- __result = (_Obj*)__chunk;
- *__my_free_list = __next_obj = (_Obj*)(__chunk + __n);
- for (__i = 1; ; __i++) {
- __current_obj = __next_obj;
- __next_obj = (_Obj*)((char*)__next_obj + __n);
- if (__nobjs - 1 == __i) {
- __current_obj -> _M_free_list_link = 0;
- break;
- } else {
- __current_obj -> _M_free_list_link = __next_obj;
- }
- }
- return(__result);
- }
- __current_obj -> _M_free_list_link = 0;
- /* __p may not be 0 */
- static void deallocate(void* __p, size_t __n)
- {
- if (__n > (size_t) _MAX_BYTES)
- malloc_alloc::deallocate(__p, __n);
- else {
- _Obj* __STL_VOLATILE* __my_free_list
- = _S_free_list + _S_freelist_index(__n);
- _Obj* __q = (_Obj*)__p;
- // acquire lock
- # ifndef _NOTHREADS
- /*REFERENCED*/
- _Lock __lock_instance;
- # endif /* _NOTHREADS */
- __q -> _M_free_list_link = *__my_free_list;
- *__my_free_list = __q;
- // lock is released here
- }
- }
- template <bool threads, int inst>
- void*
- __default_alloc_template<threads, inst>::reallocate(void* __p,
- size_t __old_sz,
- size_t __new_sz)
- {
- void* __result;
- size_t __copy_sz;
- if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) {
- return(realloc(__p, __new_sz));
- }
- if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return(__p);
- __result = allocate(__new_sz);
- __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz;
- memcpy(__result, __p, __copy_sz);
- deallocate(__p, __old_sz);
- return(__result);
- }