程序员的自我修养(6)

内存布局

1.程序员的内存布局
除了操作系统内核使用的空间,剩下的为用户空间。应用程序使用的内存空间通常有几个部分,堆与栈,可执行文件映像,保留区。
2.栈
在计算机中,栈是一个非常重要的结构,先进后出,,与经常出现的队列相反(先进先出)。在经典操作系统中,栈总是向下增长的,那么就会有一个栈顶,压栈操作让栈顶的地址减小,出栈让栈顶的地址增大。
可能没有讲清除,栈顶是栈出入数据的地址,当压入数据,栈就会向下压,栈顶向下走。当读取数据即出栈的时候,数据被取走,这个空间就会释放,那么栈顶就会向下走。
3.栈的堆栈帧
栈保存了一个函数调用所需要的维护信息,这被称为堆栈帧。一般包含以下内容。
函数的返回地址和参数
临时变量,包括函数的非静态局部变量以及编译器自动生成的其它临时变量
保存的上下文,包括函数调用前后需要保持不变的寄存器
4.堆
由于全局变量无法动态生成,只能在编译的时候生成。栈结构上的数据在函数返回的时候会被释放掉。在这种情况下,堆是唯一的选择。堆是一块巨大的内存空间,常常占据整个虚拟空间的绝大部分,在这片空间,程序可以直接申请一块连续内存,并自由的使用,这个块申请的内存会在程序结束或主动放弃前一直保持有效。
申请的内存操作是可以交给操作系统,但是当程序对堆的操作频繁的话,会严重影响系统和程序性能。那么这其实是交给程序的运行库,程序的运行库会直接向操作系统申请合所需要的堆内存,然后在给程序使用。
5.堆分配算法
堆空间只是向操作系统申请了大片连续内存,但是作用和怎么使用是没有规定的,程序在使用malloc申请堆空间的时候是大小不一的,若程序胡乱的获取空间与释放没有算法,就会导致零碎的空间很多,甚至可能发生分割的内存总和很多,但是大块的很少甚至没有,就会导致大的空间无法申请,浪费内存。
这里有三种算法与方法
1.空闲链表
就是将堆中各个空闲块按照链表连接,当用户需要一块空间时,可以遍历整个列表,直到找到合适大小的块并且将其拆分,当用户释放的时候重新合并到空闲链接链表中。
申请内存碎片会少,链表不安全,会浪费内存用于存储链表指针等其它信息。
2.位图
将整个堆划分为大量的块,每个块的大小相等,当用户需要的时候,总是分配整数的块,我们可以使用一个整数数组来记录每个块的使用情况。
速度快,稳定性好,容易管理
分配容易产生内存碎片
堆过大或快设定的大小过小,会导致位图会很大,寻找时间会多与浪费空间
3.对象池
可以将堆空间分配为几种固定的数值,我们申请的内存就会直接分配合适的大小空间,就是假设需要分配的空间大小变化不是很大。对象池的管理方法可以使用空闲链表或位图都可以。

你可能感兴趣的:(程序员的自我修养,底层,内存布局)