7.6 C程序的存储空间布局

7.6 C程序的存储空间布局

由于历史原因,C程序一直由下列几部分组成:

正文段。这是由CPU执行的机器指令部分。通常,正文段是可共享的,所以即使是经常执行的程序(如文本编辑程序、C编译程序、shell)在存储器中也只需有一个副本,另外,正文段常常是只读的,以防止程序由于意外事故而修改其自身的指令。

初始化数据段(函数外)。通常将此段称为数据段,它包含了程序中需赋初值的变量。例如, C程序中任何函数之外的说明:

int maxcount = 99;

使此变量以初值存放在初始化数据段中。

非初始化数据段(函数外)。通常将此段称为bss段,这一名称来源于早期汇编程序的一个操作符,意思是“block started by symbol(由符号开始的块)”,在程序开始执行之前,内核将此段初始化为0或空指针。出现在任何函数外的C声明为:

long sum[1000] ;

使此变量存放在非初始化数据段中。

栈。自动变量以及每次函数调用时所需保存的信息都存放在此段中。每次函数调用时,其返回地址、以及调用者的环境信息(例如某些机器寄存器)都存放在栈中。然后,新被调用的函数在栈上为其自动和临时变量分配存储空间。通过以这种方式使用栈, C函数可以递归调用。递归函数每次调用自身时,就使用一个新的栈帧,因此一个函数调用实例中的变量集不会影响另一个函数调用实例中的变量。

堆。通常在堆中进行动态存储分配。由于历史上形成的惯例,堆位于非初始化数据段顶和栈底之间。

7 – 3显示了这些段的一种典型安排方式。这是程序的逻辑布局—虽然并不要求一个具体实现一定以这种方式安排其存储空间但这是一种便于说明典型安排。

      对于x86处理器上的Linux,正文段从0x08048000单元开始,栈底则在0xC0000000之下开始,在这种特定结构中,栈从高地址向低地址方向增长。堆顶和栈底之间未用的虚拟地址空间很大。

      从上图可以看出,未初始化数据段的内容并不存放在磁盘上的程序文件中,原因是,内核在程序开始运行前将他们都设置为0需要存放在程序文件中的段只有正文段和初始化数据段

size ( 1 )命令报告正文段、数据段和b s s段的长度(单位:字节)。例如:

$ size /bin/cc /bin/sh

text     data    bss      dec     hex

81920 16384 664 98968 18298 /bin/cc

90112 16384 0 106496 1a000 /bin/sh

4和第5列是分别以十进制和十六进制表示的总长度。