C语言变量的内存分配及储存位置的探究
最近学习C语言,对变量的储存位置很不清楚,后来通过多次查询资料有了自己的见解,特写此博客分享自己对C语言在内存中的储存过程的理解,如有错误望指正。
一、虚拟内存
首先要知道,我们在应用程序中所使用的地址均是虚拟内存地址,在32位操作系统中,每一个进程所占用的虚拟内存是4G,4G的虚拟内存又分为1G的内核空间和3G的用户空间,内核空间是当前主机中所有进程共有的,用户空间是当前进程私有的,下面讲解的内存区域的划分,指的是用户空间的划分。
二、虚拟内存用户空间的区域划分
在了解了虚拟内存的基础上,我们继续看用户空间的区域划分。内存主要分为以下五个区域:
1、栈区(又称堆栈区)
存放函数的参数值、非静态局部变量等,由编译器自动分配和释放,通常在函数执行完后就释放了,其操作方式类似于数据结构中的栈。栈内存分配运算内置于CPU的指令集,效率很高,但是分配的内存量有限。
2、堆区
就是通过malloc动态分配的内存块,编译器不会负责它们的释放工作,需要用程序区释放,如果不在程序中释放则一般整个程序结束后会被系统回收内存资源。分配方式类似于数据结构中的链表。“内存泄漏”通常说的就是堆区。
3、静态区(又称静态全局区)
全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,所以静态区又分为两个段(data、bss后文详细解释)。程序结束后,由系统释放。
4、代码区
存放代码的区域
5、文字常量区
存放只读数据,如常量字符串
所以变量所在内存区(下文还有变量所在段)如下:
全局变量 -----> 静态区
静态变量 -----> 静态区
非静态局部变量、形参、返回值 -----> 栈区
动态申请的变量 -----> 堆区
代码 -----> 代码区
常量字符串 -----> 文字常量区
三、程序编译后的分段情况
源文件在编译之后生成的.o文件已经将程序进行了分段,主要有以下四个段:
1、代码段 .text
text段是程序代码段,它是由编译器在编译连接时自动计算的,当你在链接定位文件中将该符号放置在代码段后,那么该符号表示的值就是代码段大小,编译连接时,该符号所代表的值会自动代入到源程序中。
2、数据段(细分为两个段)
①已初始化段(又称全局初始化段、静态初始化段) .data
data包含静态初始化的数据,所以有初值的全局变量和static变量在data区。段的起始位置也是由连接定位文件所确定,大小在编译连接时自动分配,它和你的程序大小没有关系,但和程序使用到的全局变量,常量数量相关。
②未初始化段(又称全局未初始化段、静态未初始化段) .bss
通常是指用来存放程序中未初始化的全局变量的一块内存区域,在程序载入时由内核清0。bss段属于静态内存分配。它的初始值也是由用户自己定义的连接定位文件所确定,用户应该将它定义在可读写的ram区内,源程序中使用malloc分配