Keil中 Program Size: Code RO-data RW-data ZI-data解析

本文详细解释了程序在编译及运行时的内存布局,包括Code、RO-data、RW-data及ZI-data等部分的定义与作用。通过实例对比,帮助读者理解不同类型的变量如何影响这些内存区域的大小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      Code是代码占用的空间,RO-data Read Only 只读常量的大小,如const型,RW-data是(Read Write 初始化了的可读写变量的大小,ZI-data是(Zero Initialize 没有初始化的可读写变量的大小。ZI-data不会被算做代码里因为不会被初始化。

      简单的说就是在烧写的时候是FLASH中的被占用的空间为:Code+RO Data+RW Data

      程序运行的时候,芯片内部RAM使用的空间为: RW Data ZI Data

      Code, RO-data,RW-data ..............flash RW-data, ZIdata...................RAM

      初始化时RW-dataflash拷贝到RAM

      1; RO 看下面两段程序,他们之间差了一条语句,这条语句就是声明一个字符常量。因此按照我们之前说的,他们之间应该只会在RO数据中相差一个字节(字符常量为1字节)。 Prog1

#include void main(void)  ; 

Prog2 #include

const char a = 5

void main(void)  ; 

Prog1编译出来后的信息如下:

================================================================================ 

Code RO Data RW Data ZI Data Debug 948 60 0 96 0 Grand Totals ================================================================================

Total RO Size(Code + RO Data) 1008 ( 0.98kB) 

Total RW Size(RW Data + ZI Data) 96 ( 0.09kB) 

Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB) ================================================================================

Prog2编译出来后的信息如下:

================================================================================ 

Code RO Data RW Data ZI Data Debug 948 61 0 96 0 Grand Totals ================================================================================

Total RO Size(Code + RO Data) 1009 ( 0.99kB) 

Total RW Size(RW Data + ZI Data) 96 ( 0.09kB) 

Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB) ================================================================================

以上两个程序编译出来后的信息可以看出:Prog1Prog2RO包含了CodeRO Data两类数据。他们的唯一区别就是Prog2RO DataProg1多了1个字节。这正和之前的推测一致。 如果增加的是一条指令而不是一个常量,则结果应该是Code数据大小有差别。

      2; RW 同样再看两个程序,他们之间只相差一个“已初始化的变量”,按照之前所讲的,已初始化的变量应该是算在RW中的,所以两个程序之间应该是RW大小有区别。

Prog3

#include void main(void)  ; 

Prog4

#include char a = 5 

void main(void)  ; 

Prog3编译出来后的信息如下:

================================================================================

Code RO Data RW Data ZI Data Debug 948 60 0 96 0 Grand Totals ================================================================================

Total RO Size(Code + RO Data) 1008 ( 0.98kB) 

Total RW Size(RW Data + ZI Data) 96 ( 0.09kB) 

Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB) ================================================================================

Prog4编译出来后的信息如下:

================================================================================

Code RO Data RW Data ZI Data Debug 948 60 1 96 0 Grand Totals ================================================================================

Total RO Size(Code + RO Data) 1008 ( 0.98kB) 

Total RW Size(RW Data + ZI Data) 97 ( 0.09kB) 

Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB) ================================================================================

可以看出Prog3Prog4之间确实只有RW Data之间相差了1个字节,这个字节正是被初始化过的一个字符型变量“a”所引起的。

      3; ZI 再看两个程序,他们之间的差别是一个未初始化的变量“a”,从之前的了解中,应该可以推测,这两个程序之间应该只有ZI大小有差别。

Prog3

#include void main(void)  ; 

Prog4

#include char a void main(void)  ; 

Prog3编译出来后的信息如下:

================================================================================

Code RO Data RW Data ZI Data Debug 948 60 0 96 0 Grand Totals ================================================================================

Total RO Size(Code + RO Data) 1008 ( 0.98kB) 

Total RW Size(RW Data + ZI Data) 96 ( 0.09kB) 

Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB) ================================================================================

Prog4编译出来后的信息如下:

================================================================================

Code RO Data RW Data ZI Data Debug 948 60 0 97 0 Grand Totals ================================================================================

Total RO Size(Code + RO Data) 1008 ( 0.98kB) 

Total RW Size(RW Data + ZI Data) 97 ( 0.09kB) 

Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB) ================================================================================

编译的结果完全符合推测,只有ZI数据相差了1个字节。这个字节正是未初始化的一个字符型变量“a”所引起的。

注意:如果一个变量被初始化为0,则该变量的处理方法与未初始化华变量一样放在ZI区域。 即:ARM C程序中,所有的未初始化变量都会被自动初始化为0

 

总结: 1; C中的指令以及常量被编译后是RO类型数据。

       2; C中的未被初始化或初始化为0的变量编译后是ZI类型数据。

       3; C中的已被初始化成非0值的变量编译后市RW类型数据。 附: 程序的编译命令(假定C程序名为tst.c): armcc -c -o tst.o tst.c armlink -noremove -elf -nodebug -info totals -info sizes -map -list aa.map -o tst.elf tst.o 编译后的信息就在aa.map文件中。

       ROM主要指:NAND FlashNor Flash RAM主要指:PSRAMSDRAMSRAMDDRAM

<think>我们正在讨论Keil MDK编译后Program SizeCodeRO-dataRW-dataZI-data的含义以及它们对内存占用的影响。用户可能遇到了内存不足的问题,需要理解这些数据来优化程序。 在Keil MDK的编译输出中,Program Size通常显示如下格式: ``` Program Size: Code=xxxx RO-data=xxxx RW-data=xxxx ZI-data=xxxx ``` 这些字段分别代表: 1. **Code(代码段)**:存放程序的可执行代码(机器指令),位于Flash(ROM)中。例如函数、中断服务程序等编译后的指令。 2. **RO-data(只读数据段)**:存放程序中定义的常量(如`const`修饰的变量)和字符串常量。这部分数据也存储在Flash(ROM)中,因为它们在运行时不可修改。 3. **RW-data(可读写数据段)**:存放已初始化的全局变量和静态变量。这些变量在程序启动时会被初始化(从Flash复制到RAM中),因此它们占用两种存储空间: - Flash空间:存储初始值(在烧录时写入Flash) - RAM空间:程序运行时存放变量(在启动时从Flash复制初始值到RAM) 4. **ZI-data(零初始化数据段)**:存放未初始化或显式初始化为0的全局变量和静态变量。这些变量在程序启动时由启动代码初始化为0,因此: - 不占用Flash空间(因为初始值都是0,无需存储) - 只占用RAM空间(在运行时分配并初始化为0) ### 内存占用计算公式 - **Flash总占用** = `Code` + `RO-data` + `RW-data`(因为RW-data的初始值需要存储在Flash中) - **RAM总占用** = `RW-data` + `ZI-data`(运行时数据全部在RAM中) 例如,如果编译输出为: ``` Program Size: Code=3920 RO-data=320 RW-data=40 ZI-data=1024 ``` 则: - Flash占用 = 3920 + 320 + 40 = 4280 字节 - RAM占用 = 40 + 1024 = 1064 字节 ### 内存分布图示 ```plaintext +---------------------+ | Flash (ROM) | +---------------------+ | Code (程序代码) | 3920字节 +---------------------+ | RO-data (只读数据) | 320字节 +---------------------+ | RW-data (初始值) | 40字节 → 复制到RAM +---------------------+ +---------------------+ | RAM (运行时) | +---------------------+ | RW-data (已初始化) | 40字节 (从Flash复制初始值) +---------------------+ | ZI-data (0初始化) | 1024字节 (启动时初始化为0) +---------------------+ | 堆(Heap)和栈(Stack) | 通常不在Program Size中显示,需单独设置 +---------------------+ ``` ### 优化建议 1. **减少Flash占用**: - 优化代码(如使用编译器优化选项`-O2`、`-Os`) - 减少常量数据(如大型查找表、字符串) - 压缩数据(如将`int`数组改为`uint8_t`数组) 2. **减少RAM占用**: - 减少全局变量(改用局部变量) - 避免大数组定义为全局变量(特别是ZI-data- 动态内存分配谨慎使用(防止堆碎片) ### 查看详细内存分布 在Keil中,编译后生成的`.map`文件包含详细的内存分配情况。通过以下步骤查看: 1. 编译项目后,在`Build Output`窗口底部找到`.map`文件路径 2. 打开该文件,搜索`Memory Map of the image`查看各段地址和大小 > 提示:STM32F103C8T6的Flash为64KB(0x10000),RAM为20KB(0x5000)。若`Code+RO-data+RW-data`超过64KB,则会出现链接错误(如L6406E)[^1]。 §§相关问题§§ 1. 如何解读Keil生成的.map文件? 2. 如何优化STM32程序的RAM使用? 3. Keil中分散加载文件(Scatter File)的高级配置技巧?</think>### Keil MDK 内存占用详解(Program Size) 在 Keil MDK 编译后显示的 **Program Size** 包含四个关键参数,它们反映了程序在 STM32 微控制器中的内存分布情况: ``` Program Size: Code=3920 RO-data=320 RW-data=40 ZI-data=1024 ``` #### 1. **Code (代码段)** - **含义**:编译后的机器指令(可执行代码) - **存储位置**:Flash 存储器(非易失性) - **包含内容**: - 函数代码 - 中断服务程序 - 跳转表 - **优化建议**: - 使用编译器优化选项(`-O2`/`-O3`) - 移除未使用的函数(`--gc-sections`) - **计算公式**: $$\text{Flash占用} \geq \text{Code}$$ #### 2. **RO-data (只读数据)** - **含义**:Read-Only 常量数据 - **存储位置**:Flash 存储器 - **包含内容**: - `const` 修饰的全局变量 - 字符串常量(如 `"Hello"`) - 初始化的全局静态变量 - **示例**: ```c const uint32_t MAX_VALUE = 1000; // 计入 RO-data char *msg = "Error!"; // 字符串常量计入 RO-data ``` - **计算公式**: $$\text{Flash占用} = \text{Code} + \text{RO-data} + \text{RW-data}$$ #### 3. **RW-data (可读写数据)** - **含义**:Read-Write 初始化变量 - **存储位置**: - **Flash**:存储初始值 - **RAM**:运行时值(启动时从 Flash 复制) - **包含内容**: - 初始化的全局变量 - 初始化的静态变量 - **示例**: ```c int counter = 0; // 计入 RW-data static float calib = 1.2; // 计入 RW-data ``` - **内存关系**: $$\text{RAM占用} \geq \text{RW-data} + \text{ZI-data}$$ #### 4. **ZI-data (零初始化数据)** - **含义**:Zero-Initialized 未初始化变量 - **存储位置**:RAM - **包含内容**: - 未初始化的全局变量 - 未初始化的静态变量 - 初始化为 0 的变量 - **关键特性**: - **不占用 Flash**(启动时由启动代码初始化为 0) - **示例**: ```c uint8_t buffer[1024]; // 计入 ZI-data static char log_buf[256]; // 计入 ZI-data ``` ### 内存分布图示 ```plaintext +---------------------+ +---------------------+ | FLASH | | RAM | +---------------------+ +---------------------+ | Code (3920 bytes) | | | |---------------------| | RW-data (40 bytes) | ← 从Flash复制初始值 | RO-data (320 bytes) | |---------------------| |---------------------| | ZI-data (1024 bytes)| ← 启动时清零 | RW-data初始值(40字节)| |---------------------| +---------------------+ | Heap/Stack | (未在Program Size中显示) ``` ### 关键公式总结 1. **Flash 总占用**: $$Flash_{\text{total}} = \text{Code} + \text{RO-data} + \text{RW-data}$$ 2. **RAM 总占用**: $$RAM_{\text{total}} = \text{RW-data} + \text{ZI-data} + \text{Stack} + \text{Heap}$$ 3. **启动后最小 RAM 需求**: $$RAM_{\text{min}} = \text{RW-data} + \text{ZI-data}$$ > ⚠️ 注意:实际 RAM 占用还包括堆栈空间(需在启动文件中配置),Program Size 不显示此部分[^1]。 ### 优化策略 1. **减少 Flash 占用**: - 压缩常量数据(如使用 `uint8_t` 代替 `int`) - 启用 LTO(Link Time Optimization) 2. **减少 RAM 占用**: - 将大数组改为 `const`(移入 RO-data- 动态分配大内存(替代全局数组) 3. **监控工具**: - 查看 `.map` 文件获取详细段分布 - 使用 `fromelf --text -c xxx.axf > disasm.txt` 反汇编分析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值