禁用动态内存分配?

时间:2019-03-15 03:48:24

标签: gcc stm32 dynamic-memory-allocation

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

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

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

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

是否有一种方法可以强制执行动态内存分配,否则将导致构建失败?

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

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:0)

  

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

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


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

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

  

符合规范的实现的两种形式是托管的和独立的。合格的托管实施应接受任何严格合格的程序。符合标准的独立实现应接受任何严格符合标准的程序,在该程序中,使用库子句(第7节)中指定的功能仅限于标准标头<float.h><iso646.h>,{{1 }},<limits.h><stdalign.h><stdarg.h><stdbool.h><stddef.h><stdint.h>

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

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

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

最后,如果您使用GNU binutils链接器,则如果您的目标文件包含对malloc的任何外部引用,则始终会导致链接失败。这很容易实现-通过在Makefile中添加一些特定的配方或规则(可能使用malloc),或者使用任何合适的build automation工具(如果您的构建自动化不在链接之前允许进行这样的检查,请切换到执行以下操作的检查:makeninjaomake以及许多其他检查...。)

如果要在托管环境中的编译期间检测到nm的任何使用,则可以编写自己的GCC plugin (我觉得这太过分了,但是选择权由您决定)。或者(实际上更简单)使用一些脚本(例如,使用grep)来检测C源代码中mallocmalloc单词的出现。

请注意,在大多数托管实施中,实际上,标准函数(例如callocfprintffopenprintf(以及许多其他函数)在内部-至少有时是-使用fputc。具体来说,如果您的程序(位于托管实现之上)使用malloc,则很有可能间接使用fopen,因为在标准malloc内通常会有一些{{ 1}}是FILE-ing(通常在fopen时得到malloc-d)。

  

是否有一种方法可以强制执行动态内存分配,并且在这种情况下会使构建失败?

实际上,是的。只需在您的free中添加一些脚本就可以了。在源文件上使用fclose,或在目标文件上使用Makefile。但是,如果您在代码中使用标准的grep(来自nm),通常会在内部进行一些fopen

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

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