C程序的内存空间布局
可以查到的资料对五大内存的说法有很大的差异,以下是根据《APUE》和《C专家编程》整理的比较可信的内容:
从历史上讲,C程序一直由下面几部分组成:
1、正文段:这是由CPU执行的机器指令部分,通常正文段是可共享的,而且是只读的;
2、初始化数据段(数据段):包含了程序中需明确赋初值的变量;
/*例如C程序中出现在任何函数之外的声明*/ int maxcount = 99; /*使此变量带有其初值存放在初始化数据段中*/
3、非初始化数据段(bss段):这一名称来源于一个早期的汇编运算符,意思是"block started by symbol(由符号开始的块)",它是IBM 704机上的一个汇编伪指令,有的人把它叫做better save space(更有效的节省空间),因为bss段只保存没有值的变量,所以它并不需要保存这些变量的映像,运行时所需要的bss段大小记录在目标文件中,但bss段并不占用目标文件的任何空间,在程序开始执行之前,内核将此段中的数据初始化为0或空指针;
/*出现在任何函数外的C声明*/ long sum[1000]; /*使此变量存放在非初始化数据段中*/
4、栈:自动变量以及每次函数调用时所需保存的信息都存放在此段中,每次调用函数时,其返回地址以及调用者的环境信息(例如某些寄存器的值)都存放在栈中,然后,最近被调用的函数在栈上为其自动变量和临时变量分配存储空间,通过以这种方式使用栈,可以递归调用C函数,递归函数每次调用自身时,就使用一个新的栈帧,因此一个函数调用实例中的变量集不会影响另一个函数调用实例中的变量;
5、堆:通常在堆中进行动态存储分配,由于历史上形成的惯例,堆位于非初始化数据段和栈之间。
对于x86处理器上的linux,其典型布局如下:
--------------------------- 高地址↓ } 命令行参数和环境变量 --------------------------- 0xC0000000 栈 - - - - - - - - - - - - - - ↓向下生长 ...很大的空闲虚地址空间... ↑向上生长 - - - - - - - - - - - - - - 堆 -------------------------- 未初始化的数据 } 由exec初始化为0 -------------------------- 初始化的数据 ↘ -------------------------- 由exec从程序文件中读入 低地址↑ 正文 ↗ -------------------------- 0x08048000