есть ли конкретная уловка с хранением Arduino строка объекты в QueueArray?
когда я пытаюсь выполнить следующий код, Arduino просто перестает выполнять функцию enqueue.
QueueArray <String> q;
String s = "blah";
q.enqueue(s);
Serial.println("checkpoint"); delay(1000);
Serial.println(q.peek()); delay(1000);
Тот же код работает для хранения целых и четных (char *). что мне не хватает?
проверяя файл заголовка (только функции шаблона, а также источник):
http://playground.arduino.cc/uploads/Code/QueueArray.zip
Я считаю, что конструктор очереди приводит вас к этой проблеме.
У меня были проблемы с размещением объектов в очереди.
Я решил поместить туда ссылки только в виде числа, а затем в конце получения установить его в качестве значения адреса указателя типа объекта.
Это кстати. рискованная стратегия!
почему бы просто не использовать enqueue атрибут c_str https://www.arduino.cc/en/Reference/CStr ?
Изменить: этот ответ на комментарий будет слишком длинным:
Arduino является микропроцессором и имеет очень ограниченную память (~ 2K).
(32K для вашей программы и аналогичные во флэш-памяти).
Помните, что это также машина с ограниченным управлением памятью.
таким образом, стек и кучи очень малы, и, как правило, при использовании кучи она может очень быстро фрагментироваться.
Как программист C ++, который смотрит на ваш код, можно ожидать, что строка на самом деле выделена стеком. (подсказка: нет нового keyword
там), так что даже если внутри он будет содержать символы в куче, это позволит вам предположить, что строковый объект будет уничтожен при выходе из области видимости.
(Вы также должны ожидать, что он сам очистится и освободит динамическую память, используемую для символов. В зависимости от вашей версии библиотек это действительно работает, или возникает проблема с перераспределением / освобождением, что делает вещи хуже, чем нужно обсуждать здесь ..)
узнать разницу между кучей и стеком:
Объектная реализация C ++
Вы можете сделать что-то со строками Arduino, чтобы минимизировать фрагментацию ehap, например, зарезервировать память перед выполнением строковых операций.
Но каждый раз, когда вы решите использовать строку, вы, скорее всего, фрагментируете кучу, особенно если вы позволите ей остаться в живых после выхода из области (для использования на другом конце очереди).
Чтобы избежать проблем фрагментации, (помните, что это небольшая система), вы могли бы использовать enums
или подобное для предопределенных сообщений. Однако, если вы настаиваете, что вам действительно нужно поставить строку в очередь, у меня есть лучшее предложение.
Вы можете создать небольшой глобальный массив строк для хранения строк, которые будут закодированы. (Конечно, будет ограничен размер очереди, поскольку в очереди не может быть больше сообщений, чем позволяет массив строк).
Этот массив будет выделен в стеке, но символы, на которые ссылается каждая строка, будут выделены в куче.
Это позволяет читателю очереди очистить строку и, таким образом, освободить память в куче.
Однако, поскольку массив никогда не покидает область действия, строки никогда не удаляются отправителем автоматически.
Вам нужно будет активно очистить строку после получения строки.
Для этого решения в стеке будут постоянные издержки.
В качестве альтернативы (и, на мой взгляд, намного лучше, поскольку фрагментации не существует), вы можете использовать что-то вроде глобального символьного буфера, зарезервированного для распределения передаваемых сообщений.
Перед постановкой в очередь добавьте новое сообщение (строка с нулевым символом в конце в стиле c) после последнего, которое в данный момент находится в буфере. Очередь должна содержать указатель на сообщение в массиве char.
Вы должны всегда проверять, есть ли место в буфере для строки, прежде чем выделять какое-то новое сообщение.
Я делаю это, имея глобальный указатель «получено», который работник обновляет, когда читает сообщение.
Он просто перемещает указатель на строки, оканчивающиеся нулевым символом, когда завершает его обработку.
Затем у производителя будет другой локальный указатель, используемый для запоминания того, где он писал в последний раз, когда он что-то писал.
Поскольку полученный указатель является глобальным, производитель всегда может рассчитать «расстояние», доступное между указателями, и узнать, сколько символов можно записать в буфер сообщений.
Это простой циклический буфер, поэтому вам нужно обрабатывать переполнение и т. Д., Добавляя метод чтения и записи.
Других решений пока нет …