g++ 编译器标志以最小化二进制大小

问题描述 投票:0回答:3

我有一个 Arduino Uno R3。我正在使用 C++ 为每个传感器制作逻辑对象。 Arduino 的板载内存非常有限,为 32KB*,平均而言,我编译的对象大约为 6KB*。

我已经在使用所需的尽可能最小的数据类型,以尽量减少内存占用。是否有编译器标志来最小化二进制文件的大小,或者我是否需要使用更短的变量和函数名称、更少的函数等来最小化我的代码库?

此外,任何其他关于最小化二进制大小的提示或建议也将不胜感激。

*它可能不是以 KB 为单位来衡量的(因为我面前没有它),但 1 个对象大约是我总内存大小的 1/5,这引起了我的担忧。

c++ arduino g++ compiler-optimization
3个回答
48
投票

除了

us2012
和其他人在评论中提到的之外,还有很多减少二进制大小的技术,用我自己的一些观点总结一下:

  • 使用
    -Os
    使 gcc/g++ 优化大小。
  • 使用
    -ffunction-sections -fdata-sections
    将每个函数或数据分成翻译单元内的不同部分。将其与链接器选项
    -Wl,--gc-sections
    结合使用以消除任何未引用的部分。
  • 至少使用以下选项运行
    strip
    -s -R .comment -R .gnu.version
    。它可以与
    --strip-unneeded
    结合使用,删除所有重定位处理不需要的符号。

20
投票

如果您的代码不包含 c++-异常处理,您可以节省大量空间(在 Tuxdude 提到的所有优化步骤之后最多可节省 30k 空间)。 因此您必须提供以下标志:

-fno-exceptions

但是甚至如果你使用异常,也可以包含异常处理! 检查以下步骤:

  1. no usage of new, delete
    。如果您确实需要它,请用 malloc/free 包装器替换它们。例如搜索“tinynew.cpp”

  2. 提供纯虚拟调用的功能,例如

    extern "C" void __cxa_pure_virtual() { while(1); }

  3. 覆盖 __gnu_cxx::__verbose_terminate_handler()。它处理未处理的异常并进行名称重组,这是相当大的! (例如 d_print_comp.part.10 为 9.5k 或 d_type 为 1.8k)

干杯 弗洛


0
投票

对于需要快速构建和良好错误消息的调试,请使用

-Og -g3 -fsanitize=address -fno-omit-frame-pointer -Wall -Werror

对于您想要最小最快的二进制文件的生产:

  1. 我们先从
    -Os -fwrapv -fomit-frame-pointer -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables
    开始吧,这是非常安全的。单独添加
    -Wl,--gc-sections -fwhole-program -s -Wl,--build-id=none
    _only_ 到最后一个 gcc 步骤,将所有内容链接在一起。 (如果您将其添加到中间步骤中,事情就会崩溃并且无法正常工作。)
  2. 仅当
    grep -rnwe throw -e catch
    显示您没有使用例外情况时,才添加
    -fno-exceptions
  3. 仅当
    grep -rnwe dynamic_cast -e virtual
    显示您不使用虚拟方法或动态转换时,添加
    -fno-rtti
  4. 仅当
    grep -rnwe errno -e virtual
    显示您不使用 errno 时,才添加
    -fno-math-errno
  5. 仅当
    grep -rnwe std:
    显示您不使用动态标准库方法(类似于宏的 std,如
    std::max
    可以使用),添加
    -nodefaultlibs -lc -lgcc_s

您现在应该拥有可以获得的最小二进制文件免费/最小努力。

© www.soinside.com 2019 - 2024. All rights reserved.