C程序的内存布局

C程序运行时会被加载入内存中,而内存一般分为五个分区:栈区、堆区、数据区、常量区、代码区。

一、动态区

动态区的内容会根据执行情况而动态变化。

1、栈区(stack)
  栈区存放:函数调用时所需保存的信息(局部变量/自动变量、参数、返回值等)
  栈区大小:最大大小由编译时确定,不会太大。
 由编译器自动分配释放,由操作系统自动管理,无须手动管理。
(函数调用时自动创建,销毁时自动销毁)
  栈区地址:由高地址向低地址生长。
  栈区特点:先进后出。
 注意:
所谓的堆栈其实就是栈没有堆。
堆栈段在运行时创建,有自己固定的大小空间
若越界访问则会出现段错误(Segmentation Fault)
若多次递归调用增加栈帧导致越界则会出现栈溢出(Stack Overflow)

每次调用函数时,其返回地址以及调用者的环境信息(例如某些机器寄存器的值)都存放在栈中。然后,最近被调用的函数在栈上为其自动和临时变量分配存储空间。通过以这种方式使用栈,可以递归调用C函数。递归函数每次调用自身时,就使用一个新的栈帧,因此一个函数调用实例中的变量集不会影响另一个函数调用实例中的变量。
    在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进后出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

2、堆区(heap)
  堆区存放:程序运行中动态存储分配的空间
  堆区大小:视内存大小而定,由程序员进行分配。
  栈区地址:由低地址向高地址生长。(位于未初始化数据段和栈之间)
  注意:
手动malloc/new动态分配 , free/delete释放。

二、静态区

静态区的内容在整个程序的生命周期内都存在,由编译器在编译的时候分配。

3、数据区
  根据数据是否被初始化又分为:bss段与data段。

1.未初始化数据段(.bss)
  存放未初始化全局变量,属于静态内存分配。
  .bss不占用可执行文件空间。在程序开始执行之前,其内容由操作系统初始化(清零);
  示例:
longsum[1000] ;此变量存放在非初始化数据段中。
 bss名字来源:
来源于一个早期的汇编运算符,意思是“block started by symbol”(由符号开始的块),

2.初始化数据段(.data)
  存放已初始化的全局变量,static修饰的变量,属于静态内存分配。
  .data占用可执行文件空间。其内容由程序初始化。
 示例:
 int maxcount = 99 ;此变量带有其初值存放在初始化数据段中。

4、常量区(.rotate)
  常量区存放:存放字符串、数字等常量、const修饰的全局变量。
  程序运行期间,常量区的内容不可以被修改。

5、代码区(.text)
  代码区 = text/code segment,又叫:正文区、文本区、正文段、文本段、代码段。
  存放程序执行代码,通常程序运行前就已确定,内容不可被修改。
存放由CPU执行的机器指令部分。通常,正文段是可共享的,所以即使是频繁执行的程序(如文本编辑器、C编译器和shell等)在存储器中也只需有一个副本,另外,正文段常常是只读的,以防止程序由于意外而修改其自身的指令。