概述
在 c
语言中,堆区可以自由被开发者掌控。高度的自由也需要带来高额的管理成本,如申请后需要手动释放,本文是笔者学习堆区的笔记。
malloc和free
malloc:
参数:size
申请堆内存大小。
返回: 成功返回内存地址,失败返回NULL
macllo
内存格式:
(注意博主在vs2015中内存结构如上图所示,不同编译器有所不同)
堆类别决定系统如何管理这个块内存。
我们首先查看 intP
内存结构图:
上图堆类别写错了,这里1是指这个堆是正常类别的堆。
我们可以从右侧观察窗口看到 intP
保存的内存地址就是内存堆栈中实际使用地址即 0x010e8a78
。而补充的对地址和实际使用地址相差 0x20
大小。
我们查看一下 intP2
内存的地址为 0x010e4950
, intP
指向的下一个对地址为 0x010E4930
,当 0x010E4930
+ 0x20
= intP2
。下图为 intP2
内存结构图:
可以看到 intP2
上一个堆地址加上20偏移正好就是 IntP
。
如果开发者想在堆中添加调试信息请用如下api:
blockType
是对堆的类别 枚举如下:
define FREEBLOCK 0
define NORMALBLOCK 1
define CRTBLOCK 2
define IGNOREBLOCK 3
define CLIENTBLOCK 4
define MAXBLOCKS 5
define UNKNOWNBLOCK (-1)
举例说明:
我们跳转到对应的常量池地址
free:
释放 memblock
指向的内存。
我们看下free释放前后的区别:
释放前:释放后:同时修改上下级堆链表的内存,这里就不做讲解了。(堆内存结构会存储一个上一个堆地址和下一个堆地址,当删除一个堆的时候会进行链表删除操作)
calloc和realloc
calloc
申请 number*size
的内存大小
realloc重新给指向的地址分配新的大小。
注意 realloc
会拷贝旧内存数据到新内存地址,而后释放旧堆。并且如果新生申请内存大小大于旧的大小。不管是缩小还是放大新堆都容易引起内存碎片问题