arduino上的C++矢量占用了大量RAM

C++ vector on arduino takes up massive RAM footprint

本文关键字:RAM C++ arduino 上的      更新时间:2023-10-16

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

我想为arduino项目使用一个动态数组。我在这里发现了一个在arduino平台上使用向量的库。我使用了一个功能来监控我在这里找到的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上只有2kB的RAM可用,我将无法像目前设计的那样运行我的程序。对于具有sizeof(segment) = 16的对象segment,一个向量占用了522字节的RAM块。

所以我的问题是:

  1. 当向量的大小只有7个字节时,为什么向量会分配32*sizeof(type)字节的RAM,而不管其类型如何?

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

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

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

编辑:

向量似乎是用32的容量初始化的。

intVector.capacity() = 32;

尝试使用任一

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

不会改变矢量的容量。

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

试着打印出vec.capacity(),看看它为多少元素保留了空间。

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

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

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

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

#define __UCLIBCXX_STL_BUFFER_SIZE__ 0

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

如另一个答案中所述,std::vector总是提前分配一些内存,以防止每次插入时重新分配内存。要求系统提供更多内存是一个昂贵的过程,你需要尽可能避免。

编写一个自定义分配器分配器是std::vector的可选模板参数,有了它,你可以重新定义它如何获得内存(例如,使它预分配较小的内存量,在每次插入时重新分配,等等)。有关更多信息,你可以在STL上查看Nicolai Josuttis的网站。有一个免费章节介绍分配器(侧栏中的标题"Supplementary chapter(PDF)"),还有示例代码。