12

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

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

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

另一种选择是在系统初始化时分配 STL 容器。在初始化期间之后,不会发生额外的动态内存分配。然而,据我所知,标准的 C++ STL 数据结构不支持这一点——它要求诸如堆栈之类的容器能够被预先分配(类似于向量)。

如果对我提出的围绕标准 C 数组构建类的建议有任何评论,我将不胜感激?另外,有没有更简单的方法在编译时分配静态大小的 STL 容器,例如静态大小的堆栈或队列?(我知道矢量可以做到这一点,但其他我不确定)

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

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

4

3 回答 3

10

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

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

容器适配器实际上将要使用的实际容器类型作为其模板参数之一。因此,您可以根据需要使用 astack和 a std::list。我不一定会建议它(取决于您的用例),但您可以.

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

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

例如,如果您有一个vector需要在 2KB 内存中工作的内存,如果它的大小为 1KB,并尝试再分配 2.5KB,则分配器不能简单地返回 2KB。它可以根据请求返回 2.5KB 或throw std::bad_alloc。这是你仅有的两个选择。分配器没有办法告诉vector它它可以获得比它拥有的更多的内存,但不是它想要的那么多。

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

分配器旨在提供不同的内存区域供访问;它们不是为限制容器本身的大小而设计的。

我的建议是追踪一份 EASTL 的副本。它真的是为这种事情而设计的。我链接到的 Github 存储库有一些错误修复等,但它仍然基本相同。这不是一个糟糕的代码。它们的类 STL 容器提供了大部分接口,因此它们大多可以直接替代。但是它们提供了特殊的功能来专门控制内存分配。

于 2012-03-08T04:27:25.587 回答
2

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

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

于 2019-06-27T14:05:51.670 回答
0

除了EASTL,您还可以使用static_vectorfrom boost。它与大多数 API 共享,std::vector并且可以与容器适配器(队列、堆栈)一起使用。std::bad_alloc它可以调用而不是抛出它throw_bad_alloc(),因此它也可以在嵌入式环境中使用而没有异常。

于 2017-02-04T20:02:39.767 回答