堆区、栈区、全局区(静态区)、常量区、代码区在ROM和RAM中的分布
(1)RAM从高地址到低地址分为:栈区、堆区、全局区(也称静态区,包括.bss和.data段)、常量区、代码区。
一、栈区。栈一般存放局部变量和函数参数,从RAM的高地址,向下生长
•临时创建的局部变量存放在栈区。
•函数调用时,其入口参数存放在栈区。
•函数返回时,其返回值存放在栈区。
•const定义的局部变量存放在栈区。
这一部分的存储空间是编译器在编译代码的时候就分配好点的固定存储空间。在裸机系统中,这栈的大小由启动文件里面的代码配置。
二、堆区。
从RAM的低地址,向上生长
堆区用于存放程序运行中被动态分布的内存块,可增可减。他们的释放编译器不去管,由我们的应用程序去控制。
可以有malloc等函数实现动态分布内存。
有malloc函数分布的内存,必须用free进行内存释放,否则会造成内存泄漏。
如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
三、全局区(静态区,由.bss段和.data段组成,可读可写),存放全局变量和静态变量
.bss段
未初始化的全局变量、静态变量存放在.bss段。
初始化为0的全局变量和静态变量也存放在.bss段。
.bss段不占用可执行文件空间(其实可执行文件会记录它们的大小和位置,只是不记录他们的初值,因为没有初值,编译出来它们可能存在“code”代码段,而不是在RW和RO段。),其内容有操作系统初始化。
.data段
已经初始化的全局变量和静态变量存放在.data段。
.data段占用可执行文件空间,其内容由程序初始化。
const定义的全局变量存放在.rodata段。在有的嵌入式系统中,rodata放在ROM(如norflash)里
关于.data段为什么占用可执行文件空间的解释:因为变量已经初始化有值了,所以在链接时期,这些初值必须加入可执行文件然后下载到ROM中;但在执行时期,因为这些变量的值可能会改变,所以不能在ROM地址中寻址(可以简单的理解为ROM中存data段的数据只是存变量的初值,使用变量前也会把初值放到RAM中,变量改变后的值存放在RAM中,要去RAM中寻址),即系统在开始使用这些变量之前,必须将其初值加载到RAM中。
代码区和常量区的内容编译后会下载存储在ROM中。
四、常量区
字符串存放在常量区。
常量区的内容不可以被修改。
五、代码区
程序执行代码存放在代码区。
字符串常量也有可能存放在代码区。
keil编译完成后,窗口出现存在Code、RO-data、RW-data、ZI-data四个代码段大小。
其中Code就是代码占用大小,RO-data是只读常量、RW-data是已初始化的可读可写变量,ZI-data是未初始化的可读可写变量。
程序状态与区域 | 组成 |
(ROM)程序执行时的只读区 域(RO) | Code + RO data |
(ROM)程序存储时占用的ROM区 | Code + RO data + RW data。简单的说就是在烧写的时候是FLASH中的被占用的空间为:Code + RO Data + RW Data |
(RAM)程序执行时的可读写区域(RW) | RW data + ZI data |
RAM)程序运行的时候,芯片内部RAM使用的空间 | RW Data + ZI Data |
实时操作系统(例如uCOSIII)的任务栈其实就是一块RAM内存
局部变量:栈区
内存分四个区:静态区,栈区,堆区,代码区
分布图如下:
其他相关照片:
推荐学习:
STM32 KEIL里的MAP文件分析_map文件中data 和 section的区别-CSDN博客
在堆区开辟内存(动态内存的开辟)_knight11112的博客-CSDN博客_开辟到堆区的好处
KEIL编译后程序的大小,Code、RO-data、RW-data、ZI-data的关系_freemote的博客-CSDN博客_keil编译结果中data和code