嵌入式系统中的STL,内存非常有限

时间:2012-03-08 03:44:25

标签: c++ stl dynamic-memory-allocation deterministic static-memory-allocation

我目前正在使用带有64 KB SRAM的ARM Cortex M3处理器构建嵌入式系统。目前,我正在寻找一种方法来确保使用STL容器确定性能,其中包括确保在运行时不会最终耗尽内存。

我主要关注STL容器如何执行动态内存分配。虽然我可以利用自定义分配器让这些结构从我预留的池中获取内存,但我需要为每个结构设置一个单独的池,以确保结构的一个实例不能占用另一个实例的空间。

我正在与这个项目中的其他人一起工作,他们不想关注内存的原始分配,并且更愿意能够利用“众所周知的”数据结构(堆栈,队列,双端队列等)。因此,我正在考虑围绕C阵列构建包装器以提供这些结构。这将支持静态分配支持这些容器所需的内存,并允许其他开发人员根据编译器提供的代码大小信息知道他们在运行时之前实例化的容器的大小。在我看来,这可以保证在运行时不会发生内存中断问题,并大大简化了系统设计。

另一个选项涉及在系统初始化时分配STL容器。在初始化期之后,不会发生额外的动态内存分配。但是,据我所知,标准C ++ STL数据结构不支持这一点 - 它需要堆栈之类的容器能够预先分配(类似于向量)。

对于我围绕标准C阵列构建类的建议,我会感激吗?另外,是否有更简单的方法在编译时分配静态大小的STL容器,例如静态大小的堆栈或队列? (我知道这可能是矢量,但其他我不确定)

注意:我已经阅读了另一个问题(Embedded C++ to use STL or not),但是这个问题的作者并未明确他们有多少内存(除了他们如何使用ARM7进程)或者似乎正在考虑类似于我的解决方案。

第二个注意:我知道对于一些开发人员来说,64 KB的SRAM可能看起来像很多内存。事实上,我已经在AVR处理器上进行了大量减少内存的开发,所以我理解这个观点。但是,从我目前的(可能是不知情的)观点来看,在谈论STL容器时,64 KB的内存并不多。

3 个答案:

答案 0 :(得分:10)

这个问题有点混乱和奇怪。首先,让我们澄清一些误解。

你提到名字的“堆叠,队列,双端队列”。好吧,其中两个不是容器stackqueue是容器适配器。看,它们实际上并不直接存储元素;他们只是调解他们的界面。 stack确保您只能推送,弹出和获取顶部元素。 queue确保您只能推回,弹出并获取前面的元素(认为它也可以让你获得后面的元素)。

容器适配器实际上将要使用的实际容器类型作为其模板参数之一。因此,如果您愿意,可以使用stackstd::list。我不一定会建议它(取决于你的用例),但你可以

容器适配器不关心内存;它是使用分配内存的容器。

如果您在如此严格的内存限制系统中运行,那么您将不会发现标准容器非常友好。即使您使用allocators为它们提供固定大小的内存缓冲区,这些分配器唯一能够阻止实际容器分配更多内存的方法就是抛出异常。

例如,如果你有vector需要在2KB内存中工作,如果它的大小为1KB,并且尝试分配2.5KB以上,那么分配器不能只需返回2KB。它可以按要求返回2.5KB,也可以 throw std::bad_alloc。这是你唯一的两个选择。分配器无法告诉vector它可以获得比它拥有的内存更多的内存,但没有达到它想要的数量。

同样,分配器需要提供 new 内存,新分配的内存可以复制到其中。它不应该只提供更多的可用内存提供相同的内存。这样做可能会在某些实现中引起问题。

分配器旨在提供不同的存储区域以供访问;它们没有很好地设计用于限制容器本身的尺寸。

我的建议是追踪a copy of EASTL。它真的是为这种东西而设计的。我链接到的Github repo有一些错误修复等等,但它仍然大致相同。这不是一个糟糕的代码。他们的类似STL的容器提供了大部分接口,因此它们可以主要是直接替换。但它们提供了专门控制内存分配的特殊功能。

答案 1 :(得分:0)

除了EASTL,您还可以使用来自boost的static_vector。它与std::vector共享大部分API,并且可以与容器适配器(队列,堆栈)一起使用。它可以调用std::bad_alloc而不是抛出throw_bad_alloc(),因此它可以在嵌入式环境中使用,也可以没有例外。

答案 2 :(得分:0)

我知道这是一个旧线程,但是对于感兴趣的任何人,我都会为嵌入式应用程序维护一个类似STL的模板库。完全没有堆使用情况。

嵌入式模板库(MIT许可证) https://www.etlcpp.com