程序的存储空间布局
程序由以下几部分组成(32位一共是3G):
1.正文段
由CPU执行的机器指令部分。通常,正文段可以共享,所以即使频繁的执行程序(shell、文本编辑器等),存储器中也只需有一个副本。
正文段一般是只读的,防止程序由意外而修改其指令。
2.初始化数据段
一般称为数据段,包含了程序中需要明确地赋初始值的变量:
int maxcount=99;
3.未初始化数据段
通常称为bss段,在程序执行之前,内核将此段中的数据初始化为0或空指针,例如:
long sum[1000];
4.栈
自动变量以及每次函数调用时所需保存的信息都存放在此段中。
5.堆
通常在堆中进行动态存储分配。
图1
另外对于一个进程的虚拟地址空间来说,32位CPU,0x0000 0000 到 0xffff ffff 一共有4G的虚拟地址,其中低的3G为进程空间所用,高地址的1G空间由操作系统使用
如图2
图2
存储空间分配
C有3个函数在堆中分配空间,1个函数用来释放空间:
#include <stdlib.h>
void *malloc(size_t size);//分配指定字节数的存储区。初始值不定
void free(void *ptr);//释放空间,但不一定归还堆,而是送回可用存储区池以便后续使用
void *calloc(size_t nmemb, size_t size);//分配空间且初始化为0
void *realloc(void *ptr, size_t size);//增加或者减少分配区长度。增加长度时,可能需要将以前分配区的内容移动到另一个更大的区域
如上图1,堆是向高地址扩充的,调用realloc
时,如果有足够大的空间,可以直接在原位置想高地址方向扩充,否则需要移动换一个有足够大小的地址
当我们使用*alloc函数时,底层通常使用sbrk(2)
来扩充或缩小进程的堆。
比如我们使用malloc申请10bytes字节,底层系统调用使用sbrk像OS申请4K大小的堆空间,这样下次再调用malloc时,就直接从这4K大小的空间中分配了。
参考
http://www.cnblogs.com/clover-toeic/p/3754433.html
http://stackoverflow.com/questions/19676688/how-malloc-and-sbrk-works-in-unix