0

将 Arduino String对象存储到QueueArray中是否有特定的问题?当我尝试以下代码时,Arduino 只是在“入队”功能处停止执行。

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

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

4

1 回答 1

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++ 对象实例化

您可以使用 arduino 字符串来最小化 ehap 碎片,例如在执行字符串操作之前保留内存。

但是每次您决定使用字符串时,您很可能会将堆碎片化,特别是如果您在退出范围后让它保持活动状态(用于队列的另一端)。

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

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

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

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

我这样做的方法是拥有一个全局“已接收”指针,工作人员将在读取消息时更新。当它完成处理时,它只是将指针移动到以空字符结尾的字符串。

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

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

于 2015-11-20T11:30:36.283 回答