进程的内存布局
历史沿袭至今,C 语言程序一直都是由以下几部分组成的:
正文段 也可称为代码段,这是 CPU 执行的机器语言指令部分,文本段具有只读属性,以防止程 序由于意外而修改其指令;正文段是可以共享的,即使在多个进程间也可同时运行同一段程序。
初始化数据段 通常将此段称为数据段,包含了显式初始化的全局变量和静态变量,当程序加载到内存中时,从可执行文件中读取这些变量的值。
未初始化数据段 包含了未进行显式初始化的全局变量和静态变量,通常将此段称为 bss 段,这一 名词来源于早期汇编程序中的一个操作符,意思是“由符号开始的块”(block started by symbol), 在程序开始执行之前,系统会将本段内所有内存初始化为 0,可执行文件并没有为 bss 段变量分配 存储空间,在可执行文件中只需记录 bss 段的位置及其所需大小,直到程序运行时,由加载器来分 配这一段内存空间。
栈 函数内的局部变量以及每次函数调用时所需保存的信息都放在此段中,每次调用函数时,函数 传递的实参以及函数返回值等也都存放在栈中。栈是一个动态增长和收缩的段,由栈帧组成,系统 会为每个当前调用的函数分配一个栈帧,栈帧中存储了函数的局部变量(所谓自动变量)、实参和 返回值。
堆 可在运行时动态进行内存分配的一块区域,譬如使用 malloc()分配的内存空间,就是从系统堆 内存中申请分配的。
(此处可对照C++的虚拟内存管理)
代码段 | 包括只读存储区和文本区,其中只读存储区存储字符串常量,文本区存储程序的机器代码。 |
数据段 | 存储程序中已初始化的全局变量和静态变量 |
BSS段 | 存储未初始化的全局变量和静态变量(局部+全局) , 以及所有被初始化为0的全局变量和静态变量。 |
堆区 | 调用new/malloc函数时在堆区动态分配内存,同时需要调用delete/free来手动释放申请的内存。 |
映射区 | 存储动态链接库以及调用mmap函数进行的文件映射 |
栈 | 使用栈空间存储函数的返回地址、参数、局部变量、返回值 |
表1. c++内存管理
Linux 下的 size 命令可以查看二进制可执行文件的文本段、