为什么和何时会在C语言中无法使用malloc()函数?

3

我收到了一块基于8051的板子,上面运行着自制的嵌入式操作系统。我正在使用SDCC在OS之上创建应用程序。但是malloc不可用,所以我必须静态分配内存。为什么呢?难道malloc不应该是编译器中动态链接库的一部分吗?


1
相关阅读材料 https://dev59.com/mV0Z5IYBdhLWcg3w_0h8 - StoryTeller - Unslander Monica
1
你不能分配不存在的东西... - M.M
4
不,malloc 是标准库的一部分,不是编译器的一部分。因此,您的板子必须提供实现malloc的库。 - Paul Ogilvie
3
在RAM非常有限的系统上,动态内存分配大部分情况下都没有太多意义。 - Jabberwocky
1
@PaulOgilvie 板子,真的吗? - ringbuffer_peek
显示剩余3条评论
3个回答

8

TL;DR:

为什么和何时C语言中的malloc()函数不可用?

总体而言,每个符合标准的、托管的C实现都会提供malloc()函数,但还有其他类型,包括另一种符合标准的类型。


malloc()不应该是编译器内的动态库吗?

不完全正确。 malloc()是C标准库的一部分,因此每个符合标准的、托管的C实现都会提供它。一个C实现包括将C源代码转换为可执行程序的系统以及运行结果程序的机制和环境。前者通常围绕编译器展开。后者包括实现提供的C标准库的所有特性,如果malloc可用,则在这部分中存在。因此,严格来说,malloc()并不是编译器的组成部分。

我确信这不是你想引入的区别,但它确实与答案有关。请注意,我说malloc()托管实现提供。这些是您在通用操作系统上通常遇到的类型。它们创建通过主机OS以标准方式启动的程序,并与OS一起提供C标准库的所有特性。但也有独立实现。其中一个关键区别是,独立实现不需要提供大多数标准库,包括malloc()

您通常会发现,在嵌入式系统中使用独立实现,例如您的系统。它们还用于操作系统内核、引导加载程序和其他直接在裸机上运行的程序。您的程序在操作系统之上运行使得您的环境在嵌入式系统中有点像Cadillac,但这并不能保证C实现是托管实现。只要它不提供malloc(),它就不能成为符合标准的托管实现,但它可以成为符合标准的独立实现。它应该记录其声称的任何一个。如果它是独立的,但提供了其他标准库函数,那么您可以将其视为奢侈品。


@cleveraintwise,不,除非实现声称是符合标准的托管实现,否则不能安全地假设malloc()将在执行环境中对程序可用。 没有任何库函数需要C标准提供独立实现,甚至没有malloc(),标准对不符合要求的实现没有任何要求。 没有替代方法,只能阅读您的实现文档,至少足以检查它是否声称为符合标准的托管实现。 - John Bollinger
如果有的话,我会的。 - cleveraintwise
1
@cleveraintwise,如果没有任何文档支持,你就没有任何基础来编写代码。即使“文档”意味着从负责C实现的人口中得到的口头信息,你也必须有一些东西才能进行任何工作。 - John Bollinger
附注:缺乏文档在任何情况下都会使实现不符合规范,因为两种类型的符合规范的实现都需要记录其各种实现定义行为的选择。 - John Bollinger

2
一些对安全至关重要的系统的指南不允许动态内存分配。
例如MISRA C:2004准则有以下规定:

20.4 - 不得使用动态堆内存分配。

遵循此规则的一种方法是:不要在系统中引入或实现malloc()和其他动态内存分配函数。
这些类型的系统通常是嵌入式系统,在编译期间或之前内存需求是已知/有限的,因此可以避免使用动态内存分配而不会带来太多麻烦。

-1

通过在项目中包含C库,您可以利用malloc、printf等函数。请注意,8051是一个低内存占用设备,仅有几KB的内存。因此,包含C库会增加输出.hex文件的大小,并且可能会导致内存不足。


问题出在RAM上。除非有XDATA空间,否则在8051上最好避免使用malloc()等函数。 - Martin James
实际上,即使有XDATA RAM,在8051上最好避免使用malloc()等函数。 - Martin James
4
实际上,完全避免使用8051并不是一个不合理的方法 ;) - Martin James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接