c/c++:如何知道已用闪存的大小?

c/c++: How can I know the size of used flash memory?

本文关键字:闪存 c++ 何知道      更新时间:2023-10-16

我最近遇到了闪存溢出问题。在代码中进行了一些优化后,我保存了一些闪存并成功执行了软件。我想通过我的更改节省了多少闪存。请告诉我如何检查使用的闪存/可用闪存。我还想知道特定功能/文件使用了多少闪存。

下面提到的是有关我的开发环境的一些信息。 - 具有 64 k 内存和 512 K 闪存的 Avr 微控制器。 - 使用freeRtos。 - 使用GNU C++编译器。 - 使用AVRATJTAGEICE进行编程和调试。

请让我知道解决方案。

问候 贾加迪普。

GCC的size程序就是您正在寻找的。


size可以传递完整的编译.elf文件。默认情况下,它将输出如下内容:

$ size linked-file.elf
text    data     bss     dec     hex filename
11228     112    1488   12828    321c linked-file.elf

这是在说:

此文件的.text"部分"中有11228个字节。这通常用于函数。
112字节的初始化数据:程序中具有初始值的全局变量。
1488字节的未初始化数据:没有初始值的全局变量。

dec只是前 3 个值的总和:11228 + 112 + 1488 = 12828
hex只是dec值的十六进制表示形式:0x321c == 12828

对于嵌入式系统,通常dec需要小于目标设备的闪存大小(或设备上的可用空间)。

通常,只需观察 GCCsize命令的dectext输出就足够了,以监视编译代码的大小随时间的变化。大小的大幅跃升通常表示新功能或constexpr实现不佳,无法编译掉。(不要忘记function-sectionsdata-sections)。

注意:对于 AVR,您需要使用avr-size来检查 AVR.elf文件的链接大小。avr-size需要目标芯片的额外参数,并将自动计算所选芯片的已用闪存百分比。


GCC 的size也直接处理中间对象文件。

如果要检查函数的编译大小,这将特别有用。

你应该看到这样的摘录:

$ size -A main.cpp.o
main.cpp.o  :
section                                                                size   addr
.group                                                                    8      0
.group                                                                    8      0
.text                                                                     0      0
.data                                                                     0      0
.bss                                                                      0      0
.text._Z8sendByteh                                                        8      0
.text._ZN3XMC5IOpin7setModeENS0_4ModeE                                   64      0
.text._ZN7NamSpac6OptionIN5Clock4TimeEEmmEi                              76      0
.text.Default_Handler                                                    24      0
.text.HardFault_Handler                                                  16      0
.text.SVC_Handler                                                        16      0
.text.PendSV_Handler                                                     16      0
.text.SysTick_Handler                                                    28      0
.text._Z5errorPKc                                                         8      0
.text._ZN7NamSpac5Motor2goEi                                            368      0
.text._ZN7NamSpac5Motor3getEv                                            12      0
.rodata.cst1                                                              1      0
.text.startup.main                                                      632      0
.text._ZN7NamSpac7Program3runEv                                         380      0
.text._ZN7NamSpac8Position4tickEv                                        24      0
.text.startup._GLOBAL__sub_I__ZN7NamSpac7displayE                       292      0
.init_array                                                               4      0
.bss._ZN5Debug9formatterE                                                 4      0
.rodata._ZL10dispDigits                                                   8      0
.bss.position                                                             4      0
.bss.motorState                                                           4      0
.bss.count                                                                4      0
.rodata._ZL9diameters                                                    20      0
.bss._ZN7NamSpac8diameterE                                               16      0
.bss._ZN5Debug3pinE                                                      12      0
.bss._ZN7NamSpac7displayE                                                24      0
.rodata.str1.4                                                          153      0
.rodata._ZL12dispSegments                                                32      0
.bss._ZL16diametersDisplay                                               10      0
.bss.loadAggregate                                                        4      0
.bss.startCount                                                           4      0
.bss._ZL15runtimesDisplay                                                10      0
.bss._ZN7NamSpac7runtimeE                                                16      0
.bss.startTime                                                            4      0
.rodata._ZL8runtimes                                                     20      0
.comment                                                                111      0
.ARM.attributes                                                          49      0
Total                                                                  2494

请让我知道解决方案。

对不起,没有解决方案!您必须了解链接到最终ELF的内容,并确定它是有意链接的还是不需要的默认值。

请告诉我如何检查使用的闪存/可用闪存。

这主要取决于您的实际目标硬件平台,因此您必须设法使您的.text部分适合那里。

我还想知道特定功能/文件使用了多少闪存。

GCC binutils 的nm工具提供有关在 ELF 文件中找到的任何(全局)符号及其在其相关部分中占用的空间的详细信息。您只需要grep特定函数/类/命名空间的结果(最好去破坏!)即可累积部分类型和符号过滤输出以进行分析。

这就是方法,我一直在用一个叫做nmalyzr的小工具。很抱歉,当它站在 GIT 存储库上时,它并没有真正按预期工作(我有工作版本,没有被推迟)。


一般来说,追逐具有#include <iostream>语句的代码(无论是否使用std::cout或类似语句,都提供了静态实例!)或不需要的newlib/libstdc++绑定(例如默认异常处理)是一个很好的策略。

在生成的 elf 文件上使用 binutilssize命令。由于您似乎使用 AVR 芯片,请使用avr-size.

要获取函数的大小,请使用 binutils 中的nm命令(avr-nm在 AVR 芯片上)。