我正在尝试在低资源应用程序中完全禁用动态内存分配。我从不使用malloc / free等,据我所知,我的任何依赖项都没有。
我尝试将链接器文件LinkerScript.ld
中的堆清零:
_Min_Heap_Size = 0x000; /* required amount of heap */
但这似乎不能保证没有库函数会尝试调用malloc
。
是否有一种方法可以强制执行动态内存分配,否则将导致构建失败?
该项目没有与arm-none-eabi-gcc
交叉编译的操作系统(裸机,STM32F302R8)。
答案 0 :(得分:3)
在most common gcc based Cortex-M toolchain中,库函数由 newlib C库提供。 malloc()
和朋友的newlib实现使用_sbrk()
函数为堆分配内存,该函数必须由用户软件实现。
如果您的应用程序中没有_sbrk()
,则构建将在链接时失败。找到并删除它。
您可能还想了解如何找出why a symbol is referenced或make 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工具(如果您的构建自动化不在链接之前允许进行这样的检查,请切换到执行以下操作的检查:make
,ninja
,omake
以及许多其他检查...。)
如果要在托管环境中的编译期间检测到nm
的任何使用,则可以编写自己的GCC plugin (我觉得这太过分了,但是选择权由您决定)。或者(实际上更简单)使用一些脚本(例如,使用grep)来检测C源代码中malloc
或malloc
单词的出现。
请注意,在大多数托管实施中,实际上,标准函数(例如calloc
,fprintf
,fopen
,printf
(以及许多其他函数)在内部-至少有时是-使用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 glibc或musl-libc),则可以研究其源代码并检查malloc
是否使用堆内存。