STL 内存池源码学习与思考

来源:互联网 发布:深入浅出mysql豆瓣 编辑:程序博客网 时间:2024/05/17 01:50
首先说明一下,这次学习的是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* __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)); }}

这个函数的功能网上很多人都已经有介绍,这里就不重复了,在这只提出我对这段代码一些疑问和思考,如果想错了希望大家能够帮忙指导,这里先谢过了!!

代码的中的一个处理逻辑是:

如果当前内存池中的剩余空间不足一个__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函数源码:

static  size_t _S_freelist_index(size_t __bytes) {        return (((__bytes) + (size_t)_ALIGN-1)/(size_t)_ALIGN - 1);  }
其中_ALIGN是8;这个函数在从free_list中取数据是容易理解的,比如小于8返回的大小为8对应的链表,大于8小于17返回的是大小为16对应的链,以此类推

但是个人认为将剩余空间的数据编入free_list时这个函数定位就有问题了:

比如:剩余空间大小为9,该函数返回的索引的1,对应的是大小为16的区块链表,不是应该放在大小为8的区块链表中更合理吗?

希望大家多多指教


0 0
原创粉丝点击