C++:内存管理——精简版


前言

上一篇的精简版,方便快速复习


一、四个层面的基本用法

1.1 malloc

使用方法:

void* p1=malloc(512);//512 bytes
free(p1);

1.2 new/delete

使用方法:

complex<int>* p2=new complex<int>;
delete p2;

1.2.1 new/delete expression

  • new expression
    在这里插入图片描述
# code a
Complex* pc=new Complex(1,2);
# code b
Complex* pc;
try{
void* mem =operator newsizeof(Complex));//allocate
pc=static_cast<Complex*>(mem);//cast
pc->Complex::Complex(12;//construct,只有编译器可以这样调用
}
catch(std::bad alloc){
//若allocation失败就不运行constructor
}

  • delete expression
    在这里插入图片描述

1.2.2 Array new/delete

  • 使用方式

在这里插入图片描述
在这里插入图片描述

  • cookie记录整块的长度
  • 若使用array new 后,最后delete不加 [ ],cookie记录的长度并没有随之改变,因此上图所示绿色部分是不会有内存泄漏的,都会回收到操作系统,内存泄露真正发生在调用析构函数的次数上,如上例子所示,加[ ]会调用3次析构函数,不加[ ]只调用一次析构函数,但是由于complex object是复数,内部无指针,因此此时delete不加[ ],只调用一次析构函数就足够了,不需要回收其他地方的内存,只需要回收绿色部分,也不会发生内存泄露
  • 泄漏举例
    1、string内部有一根指针
    2、若使用array new 后,最后delete不加 [ ],内存泄露发生在下图绿色部分三个箭头指向的地方
    在这里插入图片描述
    注意
  • new包括两步,分配内存和构造函数
  • 指针psa在栈上,指向new申请的内存(即图示绿色部分)
  • 绿色部分是通过new的第一步分配内存得到的
  • 绿色部分指向的三个白色长条是通过构造函数得到的

1.3 ::operator new/::operator delete

使用方法:

void* p3=::operator new(512);
::operator delete(p3);

1.31重载::operator new/::operator delete

  • vc6源码
    在这里插入图片描述
  • 重载
    在这里插入图片描述

1.32 重载operator new/operator delete

在这里插入图片描述

1.33 重载operator new[]/operator delete[]

在这里插入图片描述

1.4 C++标准库提供的allocators

  • gunc为2.9版本
    在这里插入图片描述

1.5 调用顺序及关联

  • 宏观关系
    在这里插入图片描述
  • 调用关系
    在这里插入图片描述
  • 容器中的使用
    在这里插入图片描述

二、G2.9 std::alloc运行模式(经典)

小型内存管理:

  • 减少malloc调用次数
  • 降低cookie用量
  • 内存池提升速度,降低浪费率

2.1 特点

  • freelist管理16种大小的链表
  • 超过alloc负责的大小会交给malloc处理
  • 被要求分配内存不是8的倍数,会被调整为8的倍数
  • 每次分配40个,实质使用20个,剩余20个备用,下次分配内存将会切割这部分备用的20个
    在这里插入图片描述

2.2 内嵌指针embedded pointers

2.2.1匿名union的使用

在这里插入图片描述

  • note:
//定义union,
//第一种方式:定义了一个union类型,并且定义了一个属于该类型的对象un,因此sizeof(X)=4
class X{
public:
 union UN{
  int m_nX;
  char* pchar;
 }un;
};
//第二种方式:定义了一个union类型,但并没有定义属于该类型的任何对象,
//因此理论上sizeof(X)=0,但实际上sizeof(X)=1
class X{
public:
 union UN{
  int m_nX;
  char* pchar;
 };
};
//第三种方式://定义了一个匿名的union类型,因此也就只能在X内部使用了,
//并且此种情况隐含着已经在X中定义了一个属于该匿名union类型的象,
//因此sizeof(X)=4,并且此种情况最为特殊,可以直接通过类X的对象来使用m_nX和pchar,
//例如X x;x.m_nX=10;x.pchar="Hello World!";
class X{
public:
 union {
  int m_nX;
  char* pchar;
 };
};

  • 对于前两种方式,都在类的内部定义了一个新的具有名字的型别,因此可以用这种新的类型来定义对应于该类型的对象,例如:X::UN myun;但是这种定义是要求类内部的union在定义时的修饰符为public,否则就不能在类外部定义属于他们的对象,而只能在给类X内部使用了。同理也可以知道在类内部通过typedef定义出来的新型别也是如此。

  • 需要说明的是,union用类里以第三种定义的方式出现的话,会有很奇妙的效果,非常奇妙。m_nX和pchar共享一块4个字节的内存,只要不是同时需要m_nX和pchar出现的情况都可以只利用它们其中的一个,从而节省了内存开销

2.2.2 在G2.9 std::alloc中的使用

在这里插入图片描述

2.3 详细过程

  • 1
    在这里插入图片描述
  • 2
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200803211417254.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzk5MTgyNg==,size_16,color_FFFFFF,t_70
  • 3

在这里插入图片描述

  • 4
    在这里插入图片描述

  • 5
    在这里插入图片描述

  • 6
    在这里插入图片描述

  • 7
    在这里插入图片描述

  • 8
    在这里插入图片描述

  • 9
    在这里插入图片描述

  • 10

在这里插入图片描述

  • 11(修改系统内存至1 0000)
    在这里插入图片描述
  • 12
    在这里插入图片描述
  • 13
    在这里插入图片描述
  • 思考
    在这里插入图片描述

三、 malloc/free

3.1、vc6内存分配

  • _heap_init(…)分配16个头
  • _ioinit()第一次内存分配,256字节(100h)
  • _sbh_alloc_block()将大小调整为16的倍数
  • _sbh_alloc_new_region()每个头申请内存,并添加两根指针,一个指向管理单元,一个指向可用内存(1M,虚的)
  • sbh_alloc_new_group()可用内存切片
  • _crtGetEnvironmentStringsA第二次申请内存并分配
    在这里插入图片描述

3.11分配

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.12释放

在这里插入图片描述
在这里插入图片描述

3.13再分配

在这里插入图片描述

在这里插入图片描述

3.2、内存管理之区域合并

  • 上下cookie的存在,方便了 两个相邻区域内存的 合并回收
    在这里插入图片描述

3.3、总结

  1. 将内存分层管理,更有利于归还内存给操作系统,因为块越小,遇到回收的概率越大
  2. 判断全回收:通过GROUP的cntEntnes的值来判断。若为0,则可全回收
  3. defering推迟回收:
  • _sbh_pHeaderDefer是個指针,指向一個全回收 group所属的Header。这個group原本應被释放,但暂保留(延缓释放)。当再有第二個全回收 group出现,SBH才释放道個Defer group,并将新出现的全回收 group般为Defer。
  • 如果尚未出现第二個全回收group而又从Defer group取出block完成分配,Defer指针会被取消(设为NULL)
  • _sbh_indGroupDefer是個索引,指出Region中哪個 group(#0-#31)是Defer.
  1. 当你归还(释放)所有内存块,SBH系统将呈现什麽面貌?初始状态
  2. VC malloc 和GCC allocator
    在这里插入图片描述

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值