【问题标题】:Disable dynamic memory allocation?禁用动态内存分配?
【发布时间】:2019-03-15 03:48:24
【问题描述】:

我正在尝试在资源不足的应用程序中完全禁用动态内存分配。我从不使用 malloc/free 等,据我所知,我的任何依赖项都没有。

我已尝试将链接器文件 LinkerScript.ld 中的堆归零:

_Min_Heap_Size = 0x000;  /* required amount of heap  */

但这似乎并不能保证没有库函数会尝试调用malloc

有没有办法强制不能进行动态内存分配,如果是这样,构建会失败?

此项目(裸机,STM32F302R8)上没有与arm-none-eabi-gcc 交叉编译的操作系统。

【问题讨论】:

  • 在哪个操作系统上,或者如标准所说,在哪个运行时环境上?
  • 您至少应该edit您的问题来解释更多有关您的应用程序的信息?它是托管的还是独立的?您使用的是什么 C 标准库、什么操作系统(如果有)?您的应用程序具体在做什么?为什么需要禁用堆分配?如果没有任何此类详细信息,您的问题是不清楚
  • @BasileStarynkevitch 使用gccstm32 标签强烈表明某种运行时环境严格来说是独立的,但允许用户拥有尽可能多的托管功能。

标签: gcc stm32 dynamic-memory-allocation


【解决方案1】:

most common gcc based Cortex-M toolchain 中,库函数由newlib C 库提供。 malloc() 和朋友的newlib 实现使用_sbrk() 函数为堆分配内存,该函数必须由用户软件实现。

如果您的应用程序中没有_sbrk(),则构建将在链接时失败。找到它并删除它。

您可能还想了解如何找到why a symbol is referencedmake the build fail when an arbitrary library function is referenced

【讨论】:

    【解决方案2】:

    我正在尝试在低资源应用程序中完全禁用动态内存分配。

    这很不寻常。一般来说,人们限制他们的(托管)应用程序使用的动态内存(以及如何做到这一点是一个不同的问题,通常是operating system 特定的)。为什么要完全禁用它?如下所述,动态内存很可能在您的C standard library 实现中在内部使用。


    仔细阅读 C11 标准 n1570(或 C99 标准)。

    C 基本上有两种“模式”或两种“方言”:宿主 C 语言和独立 C 语言。标准的§4 Conformance 中的确切措辞是

    一致性实现的两种形式是托管的和独立的。符合要求的托管实现应接受任何严格符合要求的程序。符合标准的独立实现应接受任何严格符合标准的程序,其中库条款(第 7 条)中指定的功能的使用仅限于标准头文件<float.h><iso646.h><limits.h><stdalign.h> 的内容、<stdarg.h><stdbool.h><stddef.h><stdint.h><stdnoreturn.h>

    并且malloc 已定义(在<stdlib.h> 中声明)并且应该可用于托管 实现,并且通常在独立实现中不可用(但这是特定于实现的)。

    显然,您使用的是独立实现(因为您没有标准要求托管实现的malloc)。 GCC has -ffreestanding 模式。你应该使用它。那么<stdlib.h> 不可用,并且您的代码不能在该模式下使用标准malloc(除非它明确声明 malloc)。

    在托管实现中,您通常可以重新定义您的malloc(前提是它仍然具有标准要求的所有属性)。然后你可能会使用this 之类的东西(总是失败,但仍然符合标准,malloc 实现)。

    最后,如果您使用 GNU binutils 链接器,如果您的目标文件包含对 malloc 的任何外部引用,则链接总是会失败。通过在Makefile(可能使用nm)中添加一些特定的配方或规则,或者使用任何像样的build automation 工具(如果您的构建自动化之前不允许这样的检查),这很容易实现链接,切换到一个:makeninjaomake 和许多其他......)。

    如果您想在托管环境中编译时检测malloc的任何使用,您可以编写自己的GCC plugin这样做(我觉得是矫枉过正,但选择是你的)。或者(在实践中更简单)使用一些脚本(例如使用 grep)检测 C 源代码中出现的 malloccalloc 单词。

    请注意,在大多数托管实现中,在实践中,fprintffopenprintffputc(以及许多其他)等标准函数在内部 - 至少有时 - 使用 malloc。具体来说,如果您的程序(在托管实现之上)使用fopen,它很可能间接使用malloc,因为在标准FILE 内通常有一些堆分配缓冲区fopenmalloc- ing(通常在fclose 时间得到free-d)。

    有没有办法强制不能进行动态内存分配,如果是这样,构建会失败?

    在实践中,是的。只需在您的Makefile 中添加一些脚本即可进行此类检查。在源文件上使用grep,或者在目标文件上使用nm。但是如果你在代码中使用标准的fopen(来自<stdio.h>),它通常会在内部做一些malloc

    或者,定义您自己的总是失败的malloccalloc 和琐碎的free(如here

    在许多operating systems(您的应用程序使用的那个,如果有的话)上,有一种方法可以在运行时限制堆内存。 Linux 有setrlimit(2)RLIMIT_DATA

    如果您正在使用一些 free software 或开源 C standard library 实现(在托管环境中),例如 GNU glibcmusl-libc,您可以研究其源代码并检查 fopen 是否使用堆记忆。

    【讨论】:

    • > 这很不寻常。一般来说,人们在baremetal ebedded中限制动态内存是很常见的,不完全使用它,有很多原因,比如内存碎片,更容易控制资源,以及通常更安全的代码。分析映射文件可以估计最大堆栈使用量,其余内存全部专用于数据,堆使用要复杂得多
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 2013-07-01
    相关资源
    最近更新 更多