首先说明一下,这次学习的是STL空间配置器的源码中内存池部分的函数,下面是源码:
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*)_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)); }}_Obj* __STL_VOLATILE* __my_free_list = _S_free_list + _S_freelist_index(__bytes_left);
这个函数的功能网上很多人都已经有介绍,这里就不重复了,在这只提出我对这段代码一些疑问和思考,如果想错了希望大家能够帮忙指导,这里先谢过了!!
代码的中的一个处理逻辑是:
如果当前内存池中的剩余空间不足一个__size的但是剩余空间大于0时做如下处理(代码中标红的部分):
根据剩余空间的大小将这部分空间编入free_list中。
因为free_list分为块大小为8,16,24,32,...,128, 16个区块,所以要将剩余内存编入,首先需要根据剩余空间大小定位应该放在哪个区块链表上。
代码如下:
_Obj* __STL_VOLATILE* __my_free_list = _S_free_list + _S_freelist_index(__bytes_left);
_S_freelist_index函数源码:
其中_ALIGN是8;这个函数在从free_list中取数据是容易理解的,比如小于8返回的大小为8对应的链表,大于8小于17返回的是大小为16对应的链,以此类推static size_t _S_freelist_index(size_t __bytes) { return (((__bytes) + (size_t)_ALIGN-1)/(size_t)_ALIGN - 1); }
但是个人认为将剩余空间的数据编入free_list时这个函数定位就有问题了:
比如:剩余空间大小为9,该函数返回的索引的1,对应的是大小为16的区块链表,不是应该放在大小为8的区块链表中更合理吗?
希望大家多多指教