数据段:
1.全局变量
2.常量.rodata段
3.已初始化的静态数据(全局变量).data段
4.未初始化的静态数据(static修饰的局部变量).bss段
为什么需要静态数据?
- 全局变量 可以在任何文件,函数中使用,数据操作上更加方便。
- static修饰的局部变量,在函数中一直保存着,这可以使用static来保存某些重要的数据,使其运算后不消失,以便下次使用的时候。
注意:
- 静态数据只会被初始化一次;
- 如果静态数据未写初始化的值会默认为0;
- 静态数据的生命周期很长,会随着程序的结束才消失;
- 被static修饰的局部变量会从运行栈中移动到数据段;
- 被static修饰的全局变量变成仅有本文件可见静态数据;
- 被static修饰的函数由各文件可见,变成本文件可见的静态函数。
静态局部变量的问题:如果我定义一个全局变量a 然后我又在函数内定义一个局部变量a值,那么我会先使用哪一个a?
在编程中,如果全局变量和局部变量同名,那么在函数内部会优先使用局部变量。也就是说,你在函数内定义的局部变量 a 会遮蔽全局变量 a,函数内使用的将是局部变量 a。
- 全局变量:在函数外部定义的变量 a,作用域是全局的,可以在函数外部和内部访问。
- 局部变量:在函数内部定义的变量 a,作用域仅限于函数内部。
- 优先级:在函数内部,局部变量的优先级高于全局变量。如果函数内部定义了与全局变量同名的局部变量,那么在函数内部会使用局部变量,而不会使用全局变量。
代码段:
- 用户代码 .text
- 系统初始化代码 .init
程序员的代码,所有的静态数据以及代码编译完之后会在硬盘内放着,那些局部变量,形参,malloc()出来的堆内存,栈内存在我们的硬盘ELF可执行文件里面是没有,栈内存和堆内存都是存放在虚拟内存空间。而虚拟内存里面是数据段和代码段是对硬盘ELF可执行文件里面的数据段和代码段的复制。
也就是硬盘ELF里面的数据段和代码段直接复制到虚拟内存空间。
数据段和代码段都是在编译时编译完成时候就存在的。不是运行时就存在,在数据段和代码段这些内容编译完后,再运行到我们的虚拟内存.在时间上ELF可执行文件会比虚拟内存空间更早获得数据段和代码段。(ELF是一个二进制文件)
图片关系:

1. 程序员的代码和静态数据
- 硬盘中的ELF可执行文件
程序员编写的代码和静态数据(如全局变量、静态变量等)在编译和链接后会生成一个ELF格式的可执行文件。这个文件存储在硬盘上。
- 虚拟内存空间
当程序运行时,操作系统会将ELF可执行文件中的代码段和数据段加载到虚拟内存空间中。这些段在程序运行时被映射到虚拟地址空间中。
2. 局部变量、形参、堆内存和栈内存
- 局部变量和形参
这些变量存储在栈内存中。栈内存是运行时动态分配的,用于存储函数调用时的局部变量和参数。栈内存的分配和释放是由编译器自动管理的。
- 堆内存:
通过malloc()等函数分配的内存存储在堆中。堆内存是运行时动态分配的,需要程序员手动释放。
- 栈内存和堆内存
这些内存区域是在程序运行时由操作系统分配的,而不是在编译时确定的。它们不在ELF可执行文件中,而是在程序运行时由操作系统管理。
3. 虚拟内存空间
- 虚拟内存
虚拟内存是操作系统提供的一种内存管理机制,它将物理内存和磁盘空间结合起来,为每个进程提供一个独立的地址空间。
- 数据段和代码段
ELF可执行文件中的数据段(.data、.bss等)和代码段(.text)在程序运行时被映射到虚拟内存空间中。这些段在编译时就已经确定,但在程序运行时才被加载到内存中。
4. 时间顺序
- ELF可执行文件
在编译和链接阶段生成,存储在硬盘上。它包含程序的代码段和数据段。
- 虚拟内存空间
在程序运行时由操作系统分配和管理。数据段和代码段从ELF文件中加载到虚拟内存空间中,而栈内存和堆内存则在运行时动态分配。
总结
- ELF可执行文件
编译时生成,存储在硬盘上,包含代码段和数据段。
- 虚拟内存空间
运行时分配,包含从ELF文件加载的代码段和数据段,以及运行时动态分配的栈内存和堆内存。
- 栈内存和堆内存
运行时动态分配,不在ELF文件中。
可以说程序在运行的时候ELF提供数据段和代码段。