为什么 iostream 在 MCU 上占用这么多闪存 space?
Why does iostream take so much flash space on an MCU?
我使用 GCC 5.2.0 为 EFM32 MCU(基于 Cortex-M 内核)编译代码。当我想要 #include <iostream>
.
时,我注意到代码大小大幅增加
例如,让我们为 EFM32WG "Wonder Gecko" 芯片编译以下代码:
#include "em_device.h"
#include "em_chip.h"
#include <iostream>
int main(void)
{
CHIP_Init();
while (1) {
}
}
此代码将产生 172048 字节的代码,而没有 #include <iostream>
则只有 1440 字节。
我通常只使用 cout
进行调试输出(通过为 newlib 实现 _write
函数并将输出路由到 SWO 引脚),但看起来这种方法非常浪费,考虑到MCU 只有 256k 的闪存,只包括这个 header 将使代码用完大部分。
所以,我的问题是:为什么 包含 iostream header 使编译后的代码占用如此多的闪存 space?还有,有办法解决吗?
编辑:
编译器和链接器都是arm-none-eabi-g++
(5.2.0版本),C库是nano C库(我觉得)
这是我的 C++ 编译器标志(不包括包含路径):
-g -gdwarf-2 -mcpu=cortex-m4 -mthumb '-DEFM32WG940F256=1' -O0 -Wall -c -fmessage-length=0 -mno-sched-prolog -fno-builtin -ffunction-sections -fdata-sections -mfpu=fpv4-sp-d16 -mfloat-abi=softfp
这是我的链接器标志:
-g -gdwarf-2 -mcpu=cortex-m4 -mthumb -T "${BuildArtifactFileBaseName}.ld" --specs=nosys.specs -Xlinker --gc-sections -Xlinker -Map="${BuildArtifactFileBaseName}.map" -mfpu=fpv4-sp-d16 -mfloat-abi=softfp --specs=nano.specs
我尝试了优化和不优化,但生成的代码大小保持大致相同(优化后的大小可能小 1k)。
编辑 2
-fno-rtti
和 -fno-exceptions
对代码大小也没有帮助。
虽然编译器确实尝试消除完整的包含或其中未使用的部分,但这有时会失败。一些 headers 只是被包括在内
导致代码为 运行 - 这意味着即使您没有引用 header 中包含的任何内容,编译器也不能随意从中删除代码。
<iostream>
就是这样一个例子,因为它声明了一些全局 objects 其
在调用 main 之前,构造函数是 运行。它的包含将大致
将 STM32 的二进制大小增加 140kB。
您可以在 github.
上查看 gcc 开发人员的这种行为和推理
解决方案是避免在微控制器上使用 C 提供的打印功能,例如 printf()
。
我使用 GCC 5.2.0 为 EFM32 MCU(基于 Cortex-M 内核)编译代码。当我想要 #include <iostream>
.
例如,让我们为 EFM32WG "Wonder Gecko" 芯片编译以下代码:
#include "em_device.h"
#include "em_chip.h"
#include <iostream>
int main(void)
{
CHIP_Init();
while (1) {
}
}
此代码将产生 172048 字节的代码,而没有 #include <iostream>
则只有 1440 字节。
我通常只使用 cout
进行调试输出(通过为 newlib 实现 _write
函数并将输出路由到 SWO 引脚),但看起来这种方法非常浪费,考虑到MCU 只有 256k 的闪存,只包括这个 header 将使代码用完大部分。
所以,我的问题是:为什么 包含 iostream header 使编译后的代码占用如此多的闪存 space?还有,有办法解决吗?
编辑:
编译器和链接器都是arm-none-eabi-g++
(5.2.0版本),C库是nano C库(我觉得)
这是我的 C++ 编译器标志(不包括包含路径):
-g -gdwarf-2 -mcpu=cortex-m4 -mthumb '-DEFM32WG940F256=1' -O0 -Wall -c -fmessage-length=0 -mno-sched-prolog -fno-builtin -ffunction-sections -fdata-sections -mfpu=fpv4-sp-d16 -mfloat-abi=softfp
这是我的链接器标志:
-g -gdwarf-2 -mcpu=cortex-m4 -mthumb -T "${BuildArtifactFileBaseName}.ld" --specs=nosys.specs -Xlinker --gc-sections -Xlinker -Map="${BuildArtifactFileBaseName}.map" -mfpu=fpv4-sp-d16 -mfloat-abi=softfp --specs=nano.specs
我尝试了优化和不优化,但生成的代码大小保持大致相同(优化后的大小可能小 1k)。
编辑 2
-fno-rtti
和 -fno-exceptions
对代码大小也没有帮助。
虽然编译器确实尝试消除完整的包含或其中未使用的部分,但这有时会失败。一些 headers 只是被包括在内 导致代码为 运行 - 这意味着即使您没有引用 header 中包含的任何内容,编译器也不能随意从中删除代码。
<iostream>
就是这样一个例子,因为它声明了一些全局 objects 其
在调用 main 之前,构造函数是 运行。它的包含将大致
将 STM32 的二进制大小增加 140kB。
您可以在 github.
上查看 gcc 开发人员的这种行为和推理解决方案是避免在微控制器上使用 C 提供的打印功能,例如 printf()
。