禁用动态内存分配?

问题描述 投票:1回答:2

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

我已经尝试在链接器文件LinkerScript.ld中清零堆:

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

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

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

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

gcc stm32 dynamic-memory-allocation
2个回答
3
投票

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

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

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


0
投票

我试图在资源不足的应用程序中完全禁用动态内存分配。

这很不寻常。一般来说,人们限制了他们(托管)应用程序使用的动态内存(如何做到这一点是一个不同的问题,通常是特定的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)。海湾合作委员会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(它通常得到free-d at fclose时间)。

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

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

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

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

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