是否存在将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 *)。我错过了什么?
答案 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数组中消息的指针。
在分配一些新消息之前,您必须始终测试缓冲区中是否有空间用于字符串。
我这样做的方法是使用全局“收到”指针,工作人员在读取消息时会更新。 它只是将指针移动到结束为空字符的字符串,当它完成处理它时。
然后,生产者将有另一个本地指针用于记住上次写入内容时写入的位置。 由于收到的指针是全局的,生产者总是可以计算指针之间可用的“距离”,并知道可以将多少个字符写入消息缓冲区。
这是一个简单的循环缓冲区,因此您需要通过添加读取和写入方法来处理溢出等。