内存分配
在堆上分配内存
所谓堆是一段长度可变的虚拟内存,始于进程的未初始化数据段末尾(BSS)。通常将堆的当前内存边界称为“program break”。
我们依然结合进程内存布局看来。
改变堆的大小其实就像命令内核改变进程的program break位置一样,最初,program break正好位于未初始化数据段末尾之后。在program break的位置抬升后,程序可以访问新分配区域内的任何内存地址,而此时物理内存页尚未分配。内核会在进程首次试图访问这些虚拟内存地址时自动分配新的物理内存页。
系统调用brk()会将program break设置为参数addr所指定的位置。由于内存以页为单位进行分配,addr实际为下一个页的边界处。
当试图将program break设置为一个低于其初初始值的位置时,也就是低于&end位置时,可能会导致无法预知的问题。比如说我们常见的分段内存访问错误(segmention fault)
调用sbrk()将program break在原有地址上增加incer参数的大小,调用成功返回 前 一个program break的地址,返回的是新增大小的起始地址。(可以想到,你可以调用sbrk(0)去跟踪一个堆的情况)
malloc函数族详解
对于malloc函数我们并不陌生,学习c语言时学过malloc的用法。
malloc函数在堆上分配size字节大小的内存,返回新内存起始处的地址,⚠️所分配的内存未经初始化,若无法分配内存,malloc返回null。由于malloc返回内存块采用内存对齐的方式,在大多数硬件架构上,malloc是基于8或16字节边界来分配内存。
函数calloc()用于给一组相同对象分配内存,参数指定分配对象的数量,size指定每个对象的大小,与malloc不同,calloc会将已分配的内存初始为0。
realloc()函数通常用来调整一块内存的大小。参数ptr用来指向调整的内存,size指定所需调整的大小,函数返回指向大小调整后内存块的指针。若realloc增加了已分配内存块的大小,它不会对额外分配的内存进行初始化。
通常情况下,当增大已分配的内存时,realloc()会尝试合并在空