Arduino C ++:QueueArray不存储字符串对象?

时间:2015-11-20 11:03:42

标签: c++ arduino-due

是否存在将Arduino String对象存储到QueueArray中的特定问题? 当我尝试下面的代码时,Arduino就停止执行" enqueue"功能

QueueArray <String> q;
String s = "blah";
q.enqueue(s);
Serial.println("checkpoint"); delay(1000);
Serial.println(q.peek()); delay(1000);

相同的代码适用于存储整数,甚至(char *)。我错过了什么?

1 个答案:

答案 0 :(得分:0)

通过检查头文件(只有模板函数,所以也是源代码): http://playground.arduino.cc/uploads/Code/QueueArray.zip

我相信队列的构造函数会让你陷入麻烦之中。 我在队列中分配对象时遇到了麻烦。

我决定只将引用作为数字放在那里,然后在接收结束集上作为对象类型指针的地址值。 这是顺便说一句。风险策略!

为什么不直接使用c_str属性https://www.arduino.cc/en/Reference/CStr

编辑:对评论的回答太长了:

Arduino是一个μProcessor,内存非常有限(~2K)。 (32K用于您的程序,类似于闪存)。

请记住,它也是一台内存管理有限的机器。 所以堆栈和堆都非常小,一般来说,当使用堆时,它可以非常迅速地碎片化。

作为一个查看代码的C ++程序员,人们可能会认为字符串实际上是堆栈分配的。 (提示:那里没有新的keyword)所以即使它在内部会保存堆中的字符,这也应该允许你假设当你退出范围时会破坏字符串对象。

(你也应该期望它会自行清理,并释放用于字符的动态内存。根据你的库版本,这确实有效,或者重新分配/有问题解除分配,让事情变得比我们在这里讨论的更糟糕。)

了解堆和堆栈之间的区别: C++ Object Instantiation

你可以用arduino字符串做一些事情来最小化ehap碎片,就像在进行字符串操作之前保留内存一样。

但每次你决定使用一个字符串时,你很可能会对堆进行分段,特别是如果你在退出作用域后让它保持活着(在队列的另一端使用)。

为了避免碎片问题,(记住它是一个小系统),您可以使用enums或类似的预定义消息。但是如果你坚持你实际上需要排队一个字符串我有一个更好的建议。

您可以创建一个小的全局字符串数组,以保存将要插入的字符串。 (当然会限制队列大小,因为队列中不再有消息,而不是字符串对象允许的数组。 此数组将被堆栈分配,但每个字符串引用的字符将被堆分配。 这允许您让队列的读者清除字符串,从而释放堆上的内存。 但是,由于数组永远不会留下范围,因此发送方永远不会自动删除字符串。 收到字符串后,您必须主动清除字符串。 对于这个解决方案,堆栈上会有一些不断的开销。

或者(在我看来更好,因为碎片不存在),你可以使用类似全局字符缓冲区的东西,保留用于分配正在传输的消息。 在排队之前,在当前缓冲区中的最后一个消息之后附加新消息(c样式的空终止字符串)。队列应该包含指向char数组中消息的指针。

在分配一些新消息之前,您必须始终测试缓冲区中是否有空间用于字符串。

我这样做的方法是使用全局“收到”指针,工作人员在读取消息时会更新。 它只是将指针移动到结束为空字符的字符串,当它完成处理它时。

然后,生产者将有另一个本地指针用于记住上次写入内容时写入的位置。 由于收到的指针是全局的,生产者总是可以计算指针之间​​可用的“距离”,并知道可以将多少个字符写入消息缓冲区。

这是一个简单的循环缓冲区,因此您需要通过添加读取和写入方法来处理溢出等。