普通存放資料的原理
需要空間–>new/new–>申請空間、構造物件
new是將malloc重新封裝的,使用一次malloc,在記憶體中除了會開闢所需空間外,還會額外開闢36個位元組
通過這種形式管理空間可以防止越界訪問
普通方式存放資料是存在缺陷的
1.頻繁的向系統索要小的記憶體塊,會產生記憶體碎片。
2.頻繁的向系統索要小的記憶體塊,產生額外開銷,效率低。
3.沒有及時的釋放空間造成記憶體洩露。
4.空間不足時,無法獲取空間。
標準空間配置器
標準空間配置器只是將new,delete進行簡單的封裝,與我們平常使用的new和delete沒太大區別
重新設計空間配置器
重新設計空間配置器有一級空間配置器和二級空間配置器兩種
重新設計空間配置器會根據使用者索要空間的大小來選擇空間配置器
一級空間配置器
當使用者索要空間大於128個位元組時,會使用一級空間配置器
一級空間配置器將malloc和free進行簡單的封裝
void* allocate(位元組數):malloc
若空間充足,開闢空間成功,直接返回
若空間不充足,開闢空間失敗,啟動空間不足應對措施(函式指標)
allocate_oom (位元組數)
//將空間歸還系統
void deallocate(void* p,size_t size)
二級空間配置器
當使用者索取空間小於128個位元組時,會使用二級空間配置器
為了減少多次開闢空間造成的額外消耗,二級空間配置器會開闢乙個很大空間作為記憶體池
同時會構造乙個雜湊表,其中會有128/8=16個結點,每個結點下面會掛(n+1)*8位元組的記憶體塊,構成雜湊桶,以此來管理小的記憶體塊
空間管理如下:
void* allocate(size_t size)
}void* refill(size_t size)
void* chunk_alloc(size_t& nobjs,size_t size)
else if (leftbytes>=size)
else
}
這種處理記憶體碎片的方式雖然解決了外部存在大量的記憶體碎片的問題,但是還是會有在雜湊桶上掛的小碎片
下面是空間配置器的實現**
#pragma once
#include "tracelog.h"
typedef void(*handle_func)();
template class __mallocalloctemplate
else
}}
} static handle_func __malloc_alloc_oom_handler;
public:
static void* allocate(size_t n)
static void deallocate(void *p, size_t /* n */)
static handle_func setmallochandler(handle_func f) };
templatehandle_func __mallocalloctemplate::__malloc_alloc_oom_handler = 0;
#include void freehandle()///
template class __defaultalloctemplate
static size_t round_up(size_t bytes)
static char* chunkalloc(size_t size, size_t& nobjs)
else if (leftbytes > size)
else
size_t byetstoget = totalbytes*2 + round_up(_heapsize>>4);
__trace_debug("向系統申請%ubytes位元組\n",byetstoget);
_startfree = (char*)malloc(byetstoget);
if (_startfree == null)
++index;
}_endfree = null;
_startfree = (char*)__mallocalloctemplate<0>::allocate(byetstoget);
}_endfree = _startfree + byetstoget;
_heapsize += byetstoget;
return chunkalloc(size, nobjs);
} }static void* refill(size_t size)
// 將記憶體塊掛到自由鍊錶下面
size_t index = freelist_index(size);
__trace_debug("返回乙個,將剩餘%u個物件掛到freelist[%u]\n", nobjs-1, index);
obj* cur = (obj*)(chunk+size);
_freelist[index] = cur;
for (size_t i = 0; i < nobjs-2; ++i)
cur->_freelistlink = null;
return chunk;
} static void* allocate(size_t n)
__trace_debug("向二級空間配置器進行申請:%u bytes\n", n);
size_t index = freelist_index(n);
if (_freelist[index] == null)
else
}static void deallocate(void* p, size_t n)
else
}protected:
enum ;
enum ;
enum ;
union obj
; // 自由鍊錶配合管理
static obj* _freelist[__nfreelists];
// 記憶體池
static char* _startfree;
static char* _endfree;
static size_t _heapsize;
}; template typename __defaultalloctemplate::obj*
__defaultalloctemplate::_freelist[__nfreelists] = ;
// 記憶體池
template char* __defaultalloctemplate::_startfree = null;
template char* __defaultalloctemplate::_endfree = null;
template size_t __defaultalloctemplate::_heapsize = 0;
#ifdef __use_malloc
typedef __mallocalloctemplate<0> alloc;
#else
typedef __defaultalloctemplatealloc;
#endif // __use_malloc
void testdefaultalloc()
}templateclass ******alloc
static t* allocate(void)
static void deallocate(t *p, size_t n)
static void deallocate(t *p)
};
STL 空間配置器
stl有6大元件 容器 演算法 迭代器 仿函式 配接器 分配器。它們之間的密切關係是stl的精髓所在,容器用來存放資料,而容器存在的前提是要有分配器給它分配記憶體,接下來需要實現演算法,迭代器便作為演算法來對容器資料操作的橋梁,演算法可以使用仿函式完成不同的策略變化,配接器可修飾或套接仿函式。說了麼...
STL 空間配置器
stl空間配置器的底層原理 維護了乙個狹義的記憶體池,並且用乙個自由鍊錶來維護該記憶體池。該自由鍊錶比較類似於雜湊的開鏈法的儲存結構。源 pragma once using namespace std define throw bad alloc cerr out of memory endl ex...
STL空間配置器
一級空間配置器 ifndef malloc alloc template h define malloc alloc template h if 0 include define throw bad alloc throw bad alloc elif defined throw bad alloc...