C++内存管理机制总结(侯捷)

C++内存管理机制

primitives

内存分配的每一个层次

malloc() new ::operator new() allocator::allocate()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6LAAlUVI-1651486346481)(C:\Users\whmhurry\AppData\Roaming\Typora\typora-user-images\1651323700502.png)]

A* buf = new A(3);//只能调用A的默认构造函数
A* tmp = buf;

for(int i = 0; i < size; ++i){
    new(tmp++)A(1);// 这里在tmp++的地址上创建对象
}
delete[] buf;

placement new

new(tmp)A(1);

重载

//应用程序 不可改变,不可重载
Foo* p = new Foo(x);
delete p;

//可以重载
Foo* p = (Foo*)operator new(sizeof(Foo));->::operator new(size_t);->malloc(size_t);
new(p)Foo(x);
...
p->~Foo();
operator delete(p);->operator delete(void*);->free(void*)

在这里插入图片描述

编译器行为

在这里插入图片描述

alloctor

在这里插入图片描述

per-class allocator

class Airplane{
private:
    union{
        AirplaneRep rep;
        Airplane* next;
    }
};
Airplane* newBlock = static_cast<Airplane*>(::operator new(BLOCK_SIZE*sizeof(Airplane)));
for(int i = 1; i < BLOCK_SIZE - 1; ++i){
    newBlock[i].next = &newBlock[i+1];
}

static allocator

class allocator{
public:
    void* allocate(size_t);
    void deallocate(void*, size_t);
};

class Foo{
private:
    static allocator myAlloc;
public:
    static void* operator new(size_t size){
        return myAlloc.allocate(size);
    }
    static void operator delete(void* pdead, size_t size){
        return myAlloc.allocte(pdead, size);
    }
};
allocator Foo::myAlloc;

Macro for static allocator

#define DECLARE_POOL_ALLOC()\
public:\
	static void* operator new(size_t size){
        return myAlloc.allocate(size);
    }
    static void operator delete(void* pdead, size_t size){
        return myAlloc.allocte(pdead, size);
    }
private:\
	static allocator myAlloc;

#define IMPEMENT_POOL_ALLOC(class_name)\
allocator class_name::myAlloc;

//调用
class Foo{
    DECLARE_POOL_ALLOC()
};
IMPEMENT_POOL_ALLOC(Foo)

new handle

//内存不足抛出异常之前会调用
typedef void(*new_handler){cout,,, abort();};
new_hander set_new_handler(new_handler p) throw();

std::allocator

G2.9

template<class T, class Alloc = alloc>
class vector{};
void* p = alloc::allocate(512);//512bytes
vector<string, alloc<string>>

G4.9

vector<string, _gnu_cxx_pool_alloc<string>>

embedded pointers

std::alloc

__default_alloc_template<threads, inst>::free_list[__NFREELISTS]={0,...0};
typedef __default_alloc_template<false, 0> alloc;

std::alloc源码

//第二级分配器
enum{__ALIGN = 8};//上调边界
template<bool threads, int inst>//两个参数都没有用
class __default_alloc_template{
    
};
//在chunk内建立free-list
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->free_list_link = 0;
        break;
    }else{
        current_obj->free_list_link = next_obj;
    }
}

//chunk_alloc函数
//内存不足,往右边找
for(i = size; i <= __MAX_BYTES; i+=__ALIGN){
    my_free_list = free_list + FREELIS_INDEX(i);
    p = *my_free_list;
    if(NULL != p){
        *my_free_list = p->free_list_link;
        start_free = (char*)p;
        end_free = start_free + i;
        return chunk_alloc(size, nobjs);
    }
}
end_free = 0;// memory已经山穷水尽
start_free = (char*)malloc_alloc::allocate(bytes_to_get);//这里会爆出异常

malloc/free

在这里插入图片描述

mainCRTStartup()
_heap_init()
_ioinit()
GetCommandLineA()
    _heap_alloc_base()

_heap_alloc_base()

if(size<=_sbh_threshold){
	pvReturn = _sbh_alloc_block(size);//小块内存
	if(pvReturn) return pvReturn;
}
if(size == 0) size = 1;
return HeapAlloc(_crtheap, 0, size);// 操作系统给的

_heap_init()

{
	if(_crtheap = HeapCreate(mtflag...)) == NULL)
}

_ioinit()

void _cdecl_ioinit(void){
	...
	if((pio = malloc_crt(IOINFO_ARRAY_ELTS * sizeof(ioinfo)))==NULL)
}

#ifdef _DEBUG
#define _malloc_crt malloc
...
#else
#define _THISFILE _FILE_
#define _malloc_crt(s) _malloc_dbg(s, _CRT_BLOCK, _THISFILE, _LINE_)
...
#endif

__sbh_alloc_new_region()用于管理1MB内存 16K

__sbh_alloc_new_group()

1024K / 32 = 32K 由32个group管理 每个group中有64个指针

32K拆分为8个page管理 4k为1page 16为一个paragraph

typedef struct tagGroup{
	int cntEntries;
	struct tagListHead listHead[64];
}GROUP, *PGROUP;

typedef struct tagListHead{
	struct tagEntry * pEntryNext;
	struct tagEntry * pEntryPrev;
}LISTHEAD,*PLISTHEAD;

typedef struct tagEntry{
	int sizeFront;
	struct tagEntry* pEntryNext;
	struct tagEntry* pEntryPrev;
};

ioinit(100H)+debug(24H)+cookie(8H)->调到16的边界 = 130H

给出去变为131H借由最后一位进行标记

debug(24H)= 两个指针指向前后+ 一根指针指向(“ioinit.c")+一根指针指向文件第?行发出的需求+100h内存+_CRT_BLOCK(表示给CRT使用)

ff0 - 130 = ec0

130h / 16 - 1 = 18 由第18list提供

总体具体步骤

1024K / 32 = 32K 由32个group管理 每个group中有64个指针

32K拆分为8个page管理 4k为1page (16为一个paragraph)

1page中

第一次分配

ioinit(100H)+debug(24H)+cookie(8H)->调到16的边界 = 130H

给出去变为131H借由最后一位进行标记

debug(24H)= 两个指针指向前后+ 一根指针指向(“ioinit.c")+一根指针指向文件第?行发出的需求+100h内存+_CRT_BLOCK(表示给CRT使用)

剩余:ff0H - 130H = ec0H

第二次分配

getenvironmentstring环境变量 占240H 剩C80H 仍挂最后一个链表

第三次分配

占70H 剩C10H 仍挂最后一个链表

第15次释放

释放240h内存(第二次分配得到)240h/10h = 36 利用嵌入式指针 挂到35号链表中

注意:

每次分配指针指向16bit 64*16 = 1024bit = 1k最后一个指针指向大于1k的内存(剩余内存)count++,每次释放

剩余:ec0

1.HeadAlloc(,16*sizeof(HEADER))(共16个header)分配一个header

2.p = VirtualAlloc(0, 1Mb, MEM_RESERVE,…)

3.HeapAlloc(_crtheap,sizeof(REGION));//32group

4.virtualAlloc(addr, 32Kb, MEM_COMMIT,…)

内存合并

上cookie和下cookie的作用

全回收

_sbh_pHeaderDefer指向一个全回收所属的Header

_sbh_indGroupDefer指向哪一个group

loki::allocator

基本结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PJyzl0d6-1651486346484)(C:\Users\whmhurry\AppData\Roaming\Typora\typora-user-images\1651403497745.png)]

FixedAllocator::Chunk::Init
void FixedAllocator::Chunk::Init(std::size_t blockSize, unsigned char blocks){
	pData_ = new unsigned char[blockSize * blocks];
    Reset(blockSize, blocks);
}

FixedAllocator::Chunk::Reset
void FixedAllocator::Chunk::Reset(std::size_t blockSize, unsigned char blocks){
    firstAvailableBlock_ = 0;
    blocksAvailable_ = blockSize;
    unsigned char i = 0;
    unsigned char* p = pData_;
    for(;i != blocks; p+=blockSize)
        *p = ++i;
}

FixedAllocator::Chunk::Release
void FixedAllocator::Chunk::Release(){
    delete[] pData_;
}

FixedAllocator::Chunk::Allocate

在这里插入图片描述

FixedAllocator::Chunk::Deallocate

在这里插入图片描述

other allocators

GNU C++ 对于Allocator 的描述

容器的Allocator模板实参默认为allocator

接口中的成员函数重要的有,T* allocate(size_type n, const void* hind = 0); void deallocate(T* p, size_type n);

常见

__gnu_cxx::new_allocator

__gnu_cxx::malloc_allocator

智能型

内存池:fixed-size pooling cache、bitmap_alloctor

array_alloctor

在这里插入图片描述

exemple

在这里插入图片描述

_pool_alloc

GNU4.9: vector<string, __gnu_cxx::_pool_alloc> vec;

test:

在这里插入图片描述

bitmap_alloctor

blocks(64初始)

super-blocks =use count(使用容量) + bitmap[1] + bitmap[0] + blocks

_mini_vector

在这里插入图片描述

回收

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值