C中malloc()的替代品是什么?

时间:2010-02-10 23:03:20

标签: c embedded malloc

我正在为MPC 555板编写C,需要弄清楚如何在不使用malloc的情况下分配动态内存。

13 个答案:

答案 0 :(得分:18)

通常malloc()是使用sbrk()mmap()在Unix上实现的。 (如果使用后者,则需要使用MAP_ANON标志。)

如果您的目标是Windows,VirtualAlloc可能会有所帮助。 (或多或少在功能上等同于匿名mmap()。)

更新:没有意识到你没有在一个完整的操作系统下运行,我不知何故得到的印象是,这可能是在Unix系统之上运行的家庭作业或其他东西。

如果您正在进行嵌入式工作并且没有malloc(),我认为您应该找到一些可以写入的内存范围,并编写自己的malloc()。或者带别人去。

几乎所有人借用的标准都是由Doug Lea at SUNY Oswego撰写的。例如,glibc的malloc基于此。请参阅:malloc.cmalloc.h

答案 1 :(得分:4)

如果你的运行时不支持malloc,你可以找到一个开源的malloc并调整它以自己管理一块内存。

答案 2 :(得分:4)

您可能需要查看Ralph Hempel's Embedded Memory Manager

答案 3 :(得分:3)

malloc()是一种抽象,用于允许C程序分配内存,而无需了解有关如何从操作系统实际分配内存的详细信息。如果你不能使用malloc,那么你别无选择,只能使用操作系统提供的内存分配工具。

如果您没有操作系统,则必须完全控制内存布局。对于简单系统而言,最简单的解决方案是将所有内容设置为静态和/或全局,对于更复杂的系统,您需要为堆分配器保留一部分内存,然后编写(或借用)一些使用该内存的代码。用于实现malloc的内存。

答案 4 :(得分:3)

您应该解释为什么不能使用malloc(),因为出于不同的原因可能会有不同的解决方案,并且有几个原因导致它们在小型/嵌入式系统上被禁止或不可用:

  • 关注内存碎片。在这种情况下,可以为一个或多个内存池分配固定大小内存块的一组例程。
  • 运行时没有提供malloc() - 我认为嵌入式系统的大多数现代工具集确实提供了某种方式来链接malloc()实现,但也许你使用的是无论出于何种原因在这种情况下,使用Doug Lea's public domain malloc可能是一个不错的选择,但它可能对你的系统而言太大了(我不熟悉MPC 555)。如果是这种情况,可能需要一个非常简单的自定义malloc()工具。写起来并不难,但要确保你单独测试地狱,因为它也很容易弄错。例如,我有一组非常小的例程,它们使用空闲列表中的块来使用脑死存储器分配策略(分配器可以编译时配置为第一次,最佳或最后一次)。我在初始化时给它一个char数组,随后的分配调用将根据需要拆分空闲块。它远没有Lea的malloc()那么复杂,但它相当小,所以对于简单的用途它就可以做到。
  • 许多嵌入式项目禁止使用动态内存分配 - 在这种情况下,您必须使用静态分配的结构

答案 5 :(得分:3)

答案实际上取决于您可能需要动态分配内存的原因。系统在做什么需要分配内存却不能使用静态缓冲区?该问题的答案将指导您管理内存的要求。从那里,您可以确定要用于管理内存的数据结构。

例如,我的一个朋友写了一个类似于视频游戏的东西,它将扫描线中的视频渲染到屏幕上。该团队确定将为每个扫描线分配内存,但是对于任何给定场景可以有多少字节存在特定限制。渲染每个扫描线后,释放在渲染过程中分配的所有临时对象。

为了避免内存泄漏的可能性和性能原因(这是在90年代,计算机比较慢),他们采取了以下方法:他们预先分配了一个足够大的缓冲区来满足所有的分配扫描线,根据确定所需最大尺寸的场景参数。在每条扫描线的开头,全局指针被设置到扫描线的开头。当从该缓冲区分配每个对象时,返回全局指针值,并且指针在分配的字节量之后前进到下一个机器字对齐的位置。 (这个对齐填充包括在缓冲区大小的原始计算中,并且在90年代是四个字节,但现在在某些机器上应该是16个字节。)在每个扫描线的末尾,全局指针被重置为开始缓冲区。

在“debug”版本中,有两个扫描缓冲区,在交替扫描线期间使用虚拟内存保护进行保护。此方法检测从一条扫描线到下一条扫描线使用的过时指针。

扫描线存储器的缓冲区可能被称为“池”或“竞技场”,具体取决于您询问的人。相关细节是这是一个非常简单的数据结构,它管理某个任务的内存。它不是一般的内存管理器(或者,正确的“免费商店实现”),例如malloc,这可能就是你要求的。

您的应用程序可能需要不同的数据结构来跟踪您的免费存储空间。你的申请是什么?

答案 6 :(得分:3)

自己写。由于你的分配器可能专门用于几种类型的对象,我推荐Bill Wulf和Charles Weinstock开发的Quick Fit方案。 (我无法找到这篇论文的免费副本,但很多人都可以访问ACM数字图书馆。)该论文简短易读,非常适合您的问题。

如果你需要一个更通用的分配器,我在有固定内存的机器上编程的主题上找到的最佳指南是Donald Knuth的书The Art of Computer Programming,第1卷。如果你想要例子,你可以在唐的TeX源代码TeX: The Program的历史书籍长度处理中找到好的。

最后,undergraduate textbook by Bryant and O'Hallaron代价相当昂贵,但它却以令人难以忍受的细节执行malloc

答案 7 :(得分:2)

自己写。预先分配一大块静态RAM,然后编写一些函数来获取和释放它的块。这是malloc()所做的精神,除了它要求操作系统动态分配和释放内存页。

有多种方法可以跟踪分配的内容和不分配的内容(位图,已使用/自由链接列表,二叉树等)。您应该可以通过一些选择谷歌搜索找到许多参考文献。

答案 8 :(得分:1)

malloc()及其相关功能是城里唯一的游戏。当然,您可以以您选择的任何方式推出自己的内存管理系统。

答案 9 :(得分:0)

如果从堆中分配动态内存时出现问题,您可以尝试使用alloca()从堆栈中分配内存。通常的警告适用:

  • 你回来时记忆消失了。
  • 您可以分配的内存量取决于堆栈的最大大小。

答案 10 :(得分:0)

您可能对以下内容感兴趣:liballoc

这是一个简单,易于实现的malloc / free / calloc / realloc替代品。

如果您事先知道或者可以找出设备上的可用内存区域,您还可以使用他们的libbmmm来管理这些大内存块并为liballoc提供后备存储。他们是BSD许可和免费的。

答案 11 :(得分:0)

FreeRTOS包含3个内存分配实例(包括malloc()),以实现适用于小型嵌入式系统(AVR,ARM等)的不同优化和用例。有关详细信息,请参阅FreeRTOS manual

我没有看到MPC555的端口,但根据您的需要调整代码并不困难。

答案 12 :(得分:0)

如果随编译器提供的库不提供malloc,那么它可能没有堆的概念。

堆(至少在无OS系统中)只是为动态内存分配保留的内存区域。您可以通过创建一个适当大小的静态分配数组然后提供一个接口来保留这样一个区域,以便按需提供该阵列的连续块,并管理正在使用的块并返回到堆。

一种更简洁的方法是让链接器在堆栈和静态内存分配之后从剩余的内存中分配堆。这样,堆总是自动地尽可能大,允许您简单地使用所有可用内存。这将需要修改应用程序的链接描述文件。链接器脚本特定于特定的工具链,并且在某种程度上是不可避免的。

K& R包括一个简单的malloc实现。