【问题标题】:C programming without malloc没有 malloc 的 C 编程
【发布时间】:2015-02-06 14:16:20
【问题描述】:

我必须用 C 编写嵌入式设备的白色复杂应用程序。运行时 (libc) 不支持 malloc/calloc/realloc/free 或任何其他类型的动态内存管理。

此类情况的最佳做法是什么?

编辑:

应用程序很复杂。例如,它应该进行公钥加密。 设备是特定的基于 ARM-M0 的模块。 C99 模式下的编译器是 4.6.0。它是裸机(无操作系统),64K 内存。我不在乎便携性。

【问题讨论】:

  • 您正在编写什么类型(和大小)的应用程序?适用于什么设备?用什么编译器和什么标准? (独立式 C99?)什么操作系统(或者它在裸机上)?多少内存?你关心便携性吗?请编辑您的问题以改进它...这真的太模糊了(对于具有 4 KB RAM 的 16 位微控制器和 Raspberry PI,或者对于人工心脏驱动器,答案会非常不同与一些花哨的家具小工具)
  • 真的很简单。对临时数据使用堆栈,对非临时变量和大缓冲区使用全局变量。或者如果你能负担得起大堆栈,你甚至可以在那里分配临时缓冲区。
  • 如果您有很多大型数据结构的使用来来去去,实际上可能首选将它们放在堆栈上。使用更少的空间。此外,另一种非常常见且强大的技术是使用通过链表或类似方式管理的缓冲区/结构池来处理通常使用 malloc 的许多情况。并且一定要标记你的“全局”变量static,但不管内存策略/限制如何,这都不言而喻。
  • @BasileStarynkevitch - 如果他在使用 Raspberry PI 之类的东西,他几乎肯定有可用的动态内存分配,如果他正在研究人造心脏,“最佳实践”将由项目负责人和 QA 严格执行。我猜是 cortex-m0/m3/m4 之类的东西。但同意,需要澄清。
  • 如果应用程序很复杂,您可能需要考虑使用 RTOS。面向硬件的不错选择包括:CooCox、FreeRTOS、uC/OS-II 或 uC-OS-III(非免费用于商业应用)。如果不出意外,它可以简化“主循环”和 ISR 之间的通信。我所做的任何“裸机”工作最终都会在低优先级 ISR 中完成大量工作,而这些工作真的可以由另一项任务更好地处理。

标签: c arm embedded


【解决方案1】:

你可以选择:

  • 避免任何类型的动态内存

  • 实现您自己的 mallocfree(或根据需要调整一些现有的 malloc 库)

  • 实现你自己的garbage collector(我想简单的标记和扫描可能适合你的情况)。看例如以OpenMirage 为例,表明GC-ed 方法可能有意义。阅读Gc HandBook了解更多信息。

  • 使用alloca(可能是错误的)

  • 使用区域或arena allocation 技术

顺便说一句,(例如加密)算法的复杂性与动态内存管理正交......

请注意,您可以例如自定义您的编译器链(例如,如果使用最近的GCC,则使用MELT)以例如验证与您的特定内存管理器(或 GC)相关的一些特定编码规则。

【讨论】:

  • GC 在实时系统中几乎被普遍避免,即使在允许malloc 的情况下也是如此。尽管公平地说,OP 从未声明任何实时约束。
  • 同样,64Kbytes 上的 GC 可能非常快(并且快到足以兼容软实时!),并且许多 C 或 C++ 程序正在重新发明 GC 技术(例如引用计数) )。
  • 没有,但是我遇到了几位学者,他们告诉我他们已经尝试过并取得了成功....知道....)
  • 引用计数在嵌入的东西中很常见,但从未见过mark&sweep。有时间可能得试试。另外,请记住动态内存管理技术在嵌入式应用程序中很少见(在这种规模上)的另一个重要原因是几个行业的“一成不变”规则禁止/强烈反对它,并且大多数开发人员盲目地遵循这些规则(尽管事实上大多数都有条款允许违反规则)。
  • 是的,我知道,但很遗憾(以及全球大量的金钱和时间损失)。顺便说一句,编写一个好的 malloc 可能和编写一个好的 GC 一样难。
【解决方案2】:

这取决于您需要实现的应用程序。

  1. 正如 cmets 中提到的,您可以使用全局变量来存储数据。

  2. 1234563自己的内存分配器。只需使用一个足够大的数组,其中包含一些关于已分配内容和尚未分配内容的元数据,以及一些像 malloc 和朋友一样工作的函数。创建一个足够好的内存分配器并没有那么复杂,但是您必须小心可能发生的一些错误。此外,您还必须处理内存碎片和内存分配特有的各种问题,但只要付出合理的努力,这是可行的。
  3. 此外,您可以在堆栈上创建整个数据结构,但您会失去一些动态内存分配的优势。

【讨论】:

  • RE #2:K&R 中的引用 malloc 很容易用于此目的。我已经在我知道在复杂操作完成后可以安全地吹走/重置整个堆的应用程序上执行此操作,使其下次不会出现碎片。
  • “指针的优势”是什么意思?指针并不是动态内存分配所独有的;您可以将指针指向任何内存对象。
  • 是的,但是除非您使用动态内存分配,否则您不能在函数中分配内存并保留指向它的指针,因为当函数结束时,该内存将从堆栈中释放。但这可能不是描述这一点的最佳方式:D。
猜你喜欢
  • 1970-01-01
  • 2011-04-20
  • 2019-08-07
  • 1970-01-01
  • 2023-01-22
  • 2019-07-07
  • 2012-09-12
  • 2011-10-03
  • 1970-01-01
相关资源
最近更新 更多