【问题标题】:C++ vector on arduino takes up massive RAM footprintarduino 上的 C++ 向量占用大量 RAM 空间
【发布时间】:2012-12-06 17:25:32
【问题描述】:

在任何地方都找不到解决方案。希望在这个问题上变得更加开明。

我想为 arduino 项目使用各种动态数组。我在 arduino 平台here 上发现了一个使用向量的库。我使用了一个函数来监视我发现here 的 arduino 上的可用 RAM。

这是我的代码示例:

Serial.print("Starting RAM: ");
Serial.println(freeRam());
Serial.println();

vector<int> intVector;

Serial.print("Remaining RAM after intVector declaration: ");
Serial.println(freeRam());
Serial.println();

vector<char> charVector;

Serial.print("Remaining RAM after charVector declaration: ");
Serial.println(freeRam());
Serial.println();


Serial.print("sizeof(intVector) = ");
Serial.println(sizeof(intVector));
Serial.print("sizeof(charVector) = ");
Serial.println(sizeof(charVector));

这是输出:

Starting RAM: 1684

Remaining RAM after intVector declaration: 1618

Remaining RAM after charVector declaration: 1584

sizeof(intVector) = 7
sizeof(charVector) = 7

似乎 intVector 分配占用了 RAM 的 66 字节块。看起来向量为此分配了 32*2 + 2 = 66 字节的内存。同样,charVector 分配占用了 34 个字节 (32*1 + 2)。似乎这种分配 32*sizeof(type) + 更改的模式存在于其他数据类型(例如 char、float 等)。请注意 arduino 上的 sizeof(int) = 2

我的问题是我想填充这些向量的对象大小在 10-20 字节之间。由于 ATMega328 上只有 2 kB 的 RAM,我将无法按照目前的设计运行我的程序。对于 segmentsizeof(segment) = 16 的对象,向量会占用 522 字节的 RAM 块。

所以我的问题是:

  1. 当向量的大小只有 7 字节时,尽管它有类型,为什么向量分配 32 * sizeof(type) 字节的 RAM?

  2. 有没有更好的方法在 arduino 平台上使用某种动态数组?

  3. 是否有内存管理技术可以让我使用向量?

谢谢,如果此问题重复,请提前道歉!

编辑:

看来vector初始化的容量是32。

intVector.capacity() = 32;

尝试使用任一

intVector.reserve(1); // or
intVector.resize(1);

不会改变向量的容量。

【问题讨论】:

  • 你有 C++11 吗?如果你运行vector.shrink_to_fit 会发生什么?如果在向量中添加 32 个元素,是否会增加内存使用量?
  • 我没有 C++11。我会看看我是否可以在arduino上实现它。感谢您的推荐 - 我希望它有效。
  • 你可以试试看 std::deque。

标签: c++ memory-management vector arduino ram


【解决方案1】:

为了提高效率,向量一次分配的空间比它需要的多 - 您不希望每次尝试插入单个项目时都重新分配它。即使它仍然是空的,它也很有可能初始化为 32 项的容量。

尝试打印出vec.capacity() 以了解它为多少元素保留了空间。

向量是标准容器中最节省空间的,它应该只使用每个元素所需的数量加上一些恒定的开销。

【讨论】:

  • 马克,感谢您的快速回复。 vec.capacity() = 32。从我在网上看到的其他示例来看,这似乎不是 c++ 向量的标准。我可能不得不侵入我下载的库,看看是否可以更改此设置。
【解决方案2】:

快速浏览一下vector 实现会发现它总是保留额外的__UCLIBCXX_STL_BUFFER_SIZE__ 字节内存。该预处理器符号在system_configuration.h 中定义为32

所以默认构造 vector 总是占用 32 个字节加上 vector 本身必须跟踪分配的内存、大小、容量等的任何开销。

您可以尝试将system_configuration.h 中的预处理器定义更改为

#define __UCLIBCXX_STL_BUFFER_SIZE__ 0

但是如果有任何依赖于这个空间的东西总是被分配,这可能会破坏代码。

【讨论】:

  • 或者也许一些中间地带会更安全,比如 8
【解决方案3】:

正如另一个答案中提到的,std::vector 总是提前分配一些内存,以防止每次插入时重新分配。向系统请求更多内存是一个代价高昂的过程,您应该尽可能避免。

编写自定义分配器。分配器是 std::vector 的可选模板参数,您可以使用它重新定义它如何获取内存(例如,使其预分配更小的数量,在每个插入等)。有关这方面的更多信息,您可以查看 Nicolai Josuttis 在 STL 上的 website。有一个涵盖分配器的免费章节(侧栏中的标题“补充章节(PDF)”,还有sample code

【讨论】:

  • 分配器没有定义应该分配多少保留内存。 Vector 预分配了 32 个条目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-09
  • 1970-01-01
  • 2014-12-13
  • 2019-03-28
  • 2015-03-21
  • 2018-02-14
相关资源
最近更新 更多