这里以Linux中C编程为例,有些东西可能在不同的系统中处理是不一样的
/**************运行时:内存的布局****************/
以下面这段程序为例:
// A:未初始化的全局和静态变量 int array[40]; static int num1; // B:初始化后的全局和静态变量 int num2 = 10; static int num3 = 15; int main() { // C:局部变量 int i = 3; int j; // D:可执行文件的指令 array[4] = i; j = num1; return 0; } |
(1)C源文件各对应可执行文件的部分
1、对于未初始化的全局和静态变量,它一般被存到可执行文件的BSS段,这BSS段是为了更有效的节省空间而开辟的,它只存放没有值的变量,除了运行时记录BSS段的大小外,它不占目标文件的任何空间
2、对于初始化后的全局和静态变量,它被放到了可执行文件的数据段,数据段被保存到目标文件中
3、对于局部变量,它并不会成为可执行文件的一部分,它会在运行时创建,所以这也解释局部变量的生存周期相对短的原因了
4、对于可执行文件指令,它被放入可执行文件的文本段,这个文本段最易受到编译器的优化处理
(2)查看各个段的大小
在Linux下,运行size即可得到可执行文件的各段大小,在windows下可以通过查看对应段的第一个和最后一个变量和所对应的地址来计算出各段的大小,当然,下面这个程序片段能够得到你的栈顶地址:
int main() { int i = 0; printf("The Top Stack is %p\n",&i); return 0; } |
(3)可执行文件对应内存地址段的部分
链接器会把指令部分直接拷贝到内存中,CPU会从首地址开始逐条语句开始执行
系统会为可执行文件开辟一段空间,成为虚拟地址空间,从高地址到底地址一次为:栈段、BSS段、数据段、文本段、未映射区域
1、可执行文件的BSS段、数据段、文本段一一对应这内存中的BSS段、数据段、文本段
2、栈段:保存程序的局部变量、临时数据、函数参数等
3、虚拟地址空间的最底端是未映射区域,它位于进程的地址空间,但是并未赋予它物理地址,它一般用于捕捉对空指针使用的情况
(注意:BSS段和数据段有时又合称为数据段,在数据段中有一个区域是堆区域,相对于可自增长的栈段而言,堆区域也是一段可自增长的区域,它通过动态内存申请增长)