栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

C++内存管理机制

文章目录
  • C++内存管理机制
    • primitives
      • 内存分配的每一个层次
      • placement new
      • 重载
      • 编译器行为
      • alloctor
      • per-class allocator
      • static allocator
      • Macro for static allocator
      • new handle
    • std::allocator
      • embedded pointers
      • std::alloc
      • std::alloc源码
    • malloc/free
      • 总体具体步骤
      • 内存合并
      • 全回收
    • loki::allocator
      • 基本结构
        • FixedAllocator::Chunk::Init
        • FixedAllocator::Chunk::Reset
        • FixedAllocator::Chunk::Release
        • FixedAllocator::Chunk::Allocate
        • FixedAllocator::Chunk::Deallocate
    • other allocators
      • GNU C++ 对于Allocator 的描述
        • 常见
        • 智能型
          • array_alloctor
        • _pool_alloc
        • bitmap_alloctor

primitives 内存分配的每一个层次

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6LAAlUVI-1651486346481)(C:UserswhmhurryAppDataRoamingTyporatypora-user-images1651323700502.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(::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 vector{};
void* p = alloc::allocate(512);//512bytes
vector>

G4.9

vector>

embedded pointers std::alloc
__default_alloc_template::free_list[__NFREELISTS]={0,...0};
typedef __default_alloc_template alloc;

std::alloc源码
//第二级分配器
enum{__ALIGN = 8};//上调边界
template//两个参数都没有用
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:UserswhmhurryAppDataRoamingTyporatypora-user-images1651403497745.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 vec;

test:

bitmap_alloctor

blocks(64初始)

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

_mini_vector

回收

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/849742.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号