0 问题:程序运行后,是不是只有栈、堆和静态存储区这三个存储区?这三个存储区是不是一个绝对概念,还是只是一个术语?
1. 程序文件的一般布局
(1) 不同代码在可执行程序中的对应关系
观察图可知:
- 初始化的全局变量和初始化的静态局部变量存储在.data中
- 未始化的全局变量和未始化的静态局部变量存储在.bss中
- 函数体中的可执行代码存储在.text中
- 图中没有栈空间和堆空间,因为图为可执行程序,可执行程序中没有栈和堆空间
- 每个可执行程序都有一个文件头(File Header),操作系统可以根据文件头判断这是一个什么样的可执行程序
2. 程序与进程(问题:可执行程序在程序运行前后有什么样的差异?)
- 程序是一个静态的概念,表现形式为一个可执行文件
- 进程是一个动态的概念,程序由操作系统加载运行之后得到进程
- 每个程序可以对应多个进程
- 每个进程只能对应一个程序
3. 面试题:包含脚本代码的文本文件是一种类型的可执行程序吗?如果是,对应什么样的进程?
如上图:
一个可执行程序被操作系统加载后得到一个进程;
脚本文件必然会对应着一个脚本解释程序,脚本文件运行后,操作系统会查找此脚本程序是否关联了脚本解释程序,如果发现已经关联了一个脚本解释程序,操作系统会直接加载这个脚本解释程序的到进程,这个进程然后读取这个脚本文件中的脚本代码,并且解释执行脚本。
脚本文件是一种可执行程序,不过这种可执行程序不能直接被操作系统加载运行,它需要一个脚本解释程序来运行,但最终一个脚本文件对应了一个进程。
4. 文件布局在内存中的映射
5. 程序的内存布局
各个段的作用:
- 堆栈段在程序运行后才正式存在,是程序运行的基础,在程序变成进程后才拥有;
- .bss段用来存储未初始化的全局变量和静态变量;
- .data段用来存储初始化的全局变量和静态变量;
- .rodata段用来存储常量值,如字符串常量;
- .text段用来存储程序中的可执行代码。
6. 程序术语的对应关系
- 静态存储区通常指程序中的.bss和.data段
- 只读存储区通常指程序中的.rodata段
- 局部变量所占空间为栈上的空间
- 动态空间为堆中的空间
- 程序可执行代码存放在.text段(代码段)中
7. 面试题:同是全局变量和静态变量,为什么初始化和未初始化的保存在不同段中?
全局变量和静态变量未初始化它的默认值为0,有初始化的全局变量和静态变量它们的值为初始值。C语言以高效为目的,将未初始化全局变量和静态变量在加载时这片内存区直接挨着的全部初始化为0,对于已经初始化的需要保存其对应的初始值,相比于未初始化的全局变量和静态变量,初始化的全局变量和静态变量复杂许多,区分对待的话效率更高。
8. 小结
- 程序源码在编译后对应可执行程序中的不同存储区;
- 程序和进程不同,程序时静态概念,进程是动态概念;
- 堆栈段是程序运行的基础,只存在于进程空间中;
- 程序可执行代码存放于.text段中,是只读的;
- .bss和.data段用于保存全局变量和静态变量。