C语言程序的内存布局

  由C语言代码(文本文件)形成可执行文件(二进制文件),需要经过编译(Compile)-汇编(Assembly)-链接(Link)3个阶段。编译器编译C代码生成汇编程序,汇编器把汇编程序形成二进制机器代码,链接器则将各个二进制代码和数据部分收集起来并组合成1个可执行文件。
  
C语言程序和数据在内存中的存储通常分为5大部分:
  1. 文本段(Text segment)
  
  2. 已初始化(读写)数据段(Initialized data segment–RW data)
  
  3. 未初始化数据段(Uninitialized data segment–BSS[Block Started by Symbol])
  
  4. 堆区(Heap)
  
  5. 栈区(Stack)
  
其中1、2和3在内存中属于静态区域(全局区域),4和5属于动态区域

1.文本段(Text segment)

  通常代码段(Code segment)和只读数据段(RO data segment,即常量区)合称为文本段。它包括实际要执行的二进制机器代码和只读常量(如字符串常量和const定义的只读常量等);它通常是共享的,多个实例之间共享文本段。

1.1 代码段(Code segment)

  通常指用来存放程序执行代码的1块内存区域,它的大小在程序运行之前就已经确定【通常属于只读,但某些架构也允许代码段为可写(修改)】。在执行程序的过程中,CPU的程序计数器(PC)指向代码段的每1条机器代码,并由处理器依次执行。【ps:代码段为程序代码在内存中的映射,1个程序在内存中可以有多个副本】

1.2 只读数据段(RO data segment)

  通常用来存放字符串常量和const只读变量(定义的常量)等,使用这些数据的方式类似查表式的操作;由于不会被更改,故存放在只读存储器中。

2.已初始化(读写)数据段(Initialized data segment–RW data)

  通常用来存放已初始化的全局变量和静态变量等。由于数据变量在程序中声明,并且具有初值,故它们需要占用存储器的空间;在程序执行时位于可读写的内存区域

3.未初始化数据段(Uninitialized data segment–BSS)

  一般用来存放未初始化的全局变量和静态变量等。它们在程序运行之前不需要占用存储器的空间。

4.堆区(Heap)

  通常用来存放进程运行中被动态分配的内存段,分配方式类似于链表(非数据结构中的堆);它的大小并不固定,可动态扩张或缩减。它只在程序运行时出现,一般由程序员分配和释放;如果程序没有释放,操作系统可能在程序(如1个进程)结束后回收内存。一般有malloc/free函数和new/delete操作符等来调用操作。

5.栈区(Stack)

  一般用来存放在函数内部使用的变量(非static)、函数的参数以及返回值等。它只在程序运行时出现,栈区由编译器自动分配和释放。由于栈的后进先出的特点,故它特别适合用来保存/恢复调用现场。比如函数的递归调用等(递归层次太深时耗时很长,甚至占用内存超出栈区内存大小)。
  
注:堆内存向上增长,栈内存向下增长【内存地址由低地址到高地址变化为向上增长】  

  下图是APUE【Unix环境高级编程】中的1个典型C语言程序内存空间分布图
  
  C语言程序的内存布局_第1张图片
  
代码举例如下:

int a=0;       //RW data
static int b=20;    //RW data
char* p1;     //BSS
const int A=5;    //Text(RO data)
int main()
{
    int b;   //Stack
    char str[]="abcdef";  //str在Stack,"abcdef"在Text(RO data)
    char *p2;   //Stack
    static int c=2;  //RW data
    char *p3="2593";   //"2593\0"在Text(RO data),p3在Stack
    p1=(char*)malloc(10*sizeof(char));//分配得到的10个字节空间在Heap
    strcpy(p1,"2593"); //"2593\0"在Text(RO data),编译器可能会将它与p3指向的"2593\0"优化成同1个地方
}

总结

  文本段(Text segment)【包括代码段(Code segment)和只读数据段(RO data)】、已初始化读写数据段(RW data)在程序链接之后产生,未初始化数据段(BSS)在程序初始化时(链接之后、运行之前加载时)开辟,而堆(Heap)和栈(Stack)在程序运行时分配和释放。

参考资料

1.C语言编程—–程序的内存布局

2.C程序的内存布局(Memory Layout)

3.C语言中内存分布及程序运行中(BSS段、数据段、代码段、堆栈)

4.C语言的内存布局

5.C语言中的内存布局
  
  
  

你可能感兴趣的:(C语言+内存布局)