概念
内存池分为两种:内部碎片
-
内部碎片:是由于采用固定大小的内存分区,当一个进程不能完全使用分给他的固定内存区域时就产生了内部碎片,通常内部碎片难以完全避免;
-
外部碎片:是由于某些未分配的连续内存区域大小,以至于不能满足任意进程的内存分配请求,从而不能额比进程利用的内存区域。
现在普遍采用的段页式内存分配方式就是将进程的内存区域分为不同的段,然后将每一段由多个固定大小的页组成。通过页表机制,使段内的页可以不必连续处于同一内存区域,从而减少了外部碎片,然而同一页内仍然可能存在少量的内部碎片,只是一页的内存空间本就较小,从而使可能存在的内部碎片也较少。
至于C语言中内存碎片该如何处理?
(当malloc/free用多了就会产生内存碎片问题)
首先,使用最原始的标记分配方法,系统需要维护一个简单的内存信息表:
ID | 内存块首地址 | 内存块尾地址 | 长度 | 状态 |
---|---|---|---|---|
1 | 1 | 10 | 10 | 空闲 |
当程序申请一个长度为3的内存空间后:
ID | 内存块首地址 | 内存块尾地址 | 长度 | 状态 |
---|---|---|---|---|
1 | 1 | 3 | 3 | |
2 | 4 | 10 | 7 | 空闲 |
当程序再申请一个长度为2,以及长度为4的内存空间后:
ID | 内存块首地址 | 内存块尾地址 | 长度 | 状态 |
---|---|---|---|---|
1 | 1 | 3 | 3 | |
2 | 4 | 5 | 2 | |
3 | 6 | 9 | 4 | |
4 | 10 | 10 | 1 | 空闲 |
此时,只剩下一个可用空间,如果这时程序再来申请长度大于1的空间,就申请不了,也就是内存不够。
现在,释放掉ID=2的空间:
ID | 内存块首地址 | 内存块尾地址 | 长度 | 状态 |
---|---|---|---|---|
1 | 1 | 3 | 3 | |
2 | 4 | 5 | 2 | 空闲 |
3 | 6 | 9 | 4 | |
4 | 10 | 10 | 1 | 空闲 |
我们发现,现在可用内存空间为3,但是,这3个空闲空间,并不是连续的。所以,如果程序现在申请长度为3的内存空间,同样会申请不了,会出现内存不够。业界把这种情况,称之为【内存碎片】。
明明是有3个空间的,却申请不到?!