GCC - 如何停止 malloc 被链接?

Posted

技术标签:

【中文标题】GCC - 如何停止 malloc 被链接?【英文标题】:GCC - How to stop malloc being linked? 【发布时间】:2018-02-02 02:43:32 【问题描述】:

我正在努力将我的代码缩减到最小的骨架大小!我正在使用只有 32k 闪存的 STM32F0,并且需要很大一部分闪存来存储数据。我的代码已经是大约 20k 闪存大小!其中一些是由于使用了 STM32 HAL 功能,我可以在以后根据需要对其进行说明和优化。

然而,我最大的 flash 消费者是所有隐式包含的库例程。我似乎无法删除这些功能。在我的代码或任何 HAL 代码中的任何地方都不会调用它们。 _malloc_r (1.3k Bytes) 和 __vfiprintf_r (3kB) 等函数以及许多其他函数都使用了我的闪存的很大一部分。我认为这些都是 libc 的功能。我不使用这些并且希望它们消失!

有人知道如何删除这些吗?

我尝试了不同的优化级别和链接器选项,但到目前为止没有运气。我试过 -nostdlib 和 --specs=nosys.specs 没有任何变化。如果我删除了包含诸如 _exit 之类的函数定义的文件,我会收到一个链接器错误,提示该库仍然包含在内并且需要这些。链接器映射也确认存在许多不需要的功能!

有什么建议吗?

【问题讨论】:

您是否尝试过显式调用链接器ld 而不是通过gcc 前端程序? 添加-v 看看ld是如何被调用的。 -nostartfiles 可能是相关的。 也许你应该使用-ffreestanding 【参考方案1】:

当您想知道什么会占用空间,或者为什么要链接函数和库时,请生成一个带有交叉引用的映射文件 - 例如“-Wl,-Map=program.map,--cref”。用文本编辑器查看文件,你就会明白为什么会包含 malloc 之类的函数。

【讨论】:

【参考方案2】:

已解决...我的一些代码包含并称为断言。在我删除断言的那一刻,我的代码大小减少了一半以上!我改为使用 STM32 HAL assert_param 宏,它是一个轻量级断言,仅重定向到用户定义的函数。

如果有人可以向我解释 gcc 在调用 assert 时如何决定包含库函数会很有帮助?我看到 assert.h 声明了一个外部函数 __assert_func。链接器如何知道从库中引用它,而不仅仅是说“对 __asert_func 的未定义引用”?

【讨论】:

根据经验,永远不要在生产版本中使用 assert()。另一个经验法则是,永远不要在嵌入式系统中使用 assert()。为给定的产品推出您自己的错误报告系统,无论如何您都可能需要一个来报告特定于产品的错误。 @Lundin 断言在 STM32 中以 #define assert_param(condition) 的方式设计,对于生产,您可以简单地进行空定义。否则我同意你的看法。 尽量使用静态断言。它们没有运行时成本,也不需要为发布版本禁用。 这个答案的后半部分可能是另一个要问的好问题 @Lundin 我会添加另一个 - void HAL 或类似 HAL 的库。

以上是关于GCC - 如何停止 malloc 被链接?的主要内容,如果未能解决你的问题,请参考以下文章

编译时如何将libevent与gcc静态链接?

LSB AppChecker:针对未使用库的 GCC 链接

gcc 编译使用动态链接库和静态链接库

如何获取 GCC 链接器命令?

GCC 编译使用动态链接库和静态链接库--及先后顺序----及环境变量设置总结

停止链接:在内容被应用于链接的规则下划线之前