Безопасно ли использовать std::string (и выделение памяти в целом) для ESP32 Arduino?

esp32 memory heap

Я знаю, что в 8-битных AVR Arduinos std::string широко рассматривается как принципиально небезопасный из-за проблем с фрагментацией кучи (частично из-за ограниченного объема оперативной памяти, а частично из-за того, что базовая библиотека Arduino/AVR управление памятью более упрощено, чем постоянное выделение и освобождение множества эфемерных выделений, необходимое).

Применяется ли то же предостережение к ESP32 (при использовании с платформой Arduino) или его базовая схема управления памятью (предположительно основанная на esp-idf) на модуле с ~468 КБ ОЗУ достаточно лучше справляется с минимизацией фрагментации и утечки памяти, чтобы сделать std::string (и другие подобные классы) безопасным в использовании без необходимости постоянно зацикливаться на проблеме и изо всех сил стараться избежать эфемерного выделения памяти?

Меня особенно беспокоит то, что различные библиотеки для выполнения http-запросов (потенциально предполагающие создание и уничтожение нескольких объектов String для каждого запроса и ответа) могут быть более безразличны к проблеме, чем им действительно должно быть быть.

Я знаю, что существует несколько библиотек Arduino, которые по сути выделяют один большой кусок памяти для многократно используемого объекта типа String (и дополнительное пространство, чтобы дать ему «рабочее пространство» для выполнения таких вещей, как регулярные выражения и замены подстроок). и т. д.), но похоже, что популярные библиотеки ESP32 для выполнения http-запросов просто создают и уничтожают новые объекты String для каждого запроса и действуют так, как будто все в порядке. У меня паранойя, или эфемерное распределение памяти по-прежнему является реальной проблемой даже на таких платформах, как ESP32?

Точно так же... есть ли какой-нибудь способ (в программе ESP32 Arduino) периодически просить библиотеку проанализировать текущую ситуацию с памятью и намеренно инициировать программную перезагрузку (и повторно -инициализация), если память становится чрезмерно фрагментированной (вместо ожидания медленной утечки памяти, которая будет продолжаться до тех пор, пока не произойдет сбой при выделении памяти и вся программа неконтролируемо выйдет из строя)?

, 👍0


2 ответа


0

Проблема случайного выделения и освобождения памяти во встроенных системах (ES) заключается в том, что большинство из них предназначены для работы без ошибок, по сути, навсегда. Поскольку объем памяти ограничен, ES, использующий этот метод, не удовлетворяет этому ограничению.

Что касается вопроса в вашем последнем абзаце, очевидно, вы рассматриваете систему, которая может допускать случайные перезагрузки с последующей потерей контекста. В этом случае, возможно, сброс в любое время при сбое распределения будет приемлемым. Вам следует проверять каждый запрос особенно тщательно, чтобы гарантировать, что он обычно будет успешным (определите «обычно»!), чтобы избежать больших накладных расходов, связанных со слишком частыми сбросами или, что еще хуже, непрерывным циклом сброса, возникающим из-за невозможного. -запрос на выполнение.

Подумайте о разнице между системой вопросов и ответов, управляемой человеком, с одной стороны, и имплантированным кардиостимулятором или системой автоматической посадки реактивного истребителя для ночных посадок на авианосец. Случайные сбои во времени могут раздражать меня в системе вопросов и ответов (если я вообще могу это заметить), но в любой из двух других это может испортить кому-то весь день. :-(

,

Система определенно может выдерживать периодические перезагрузки без происшествий, если они происходят, когда **я** решаю, что они необходимы (скажем, после проверки в качестве последнего действия в цикле() и запуска перезагрузки, если самый большой кусок свободного памяти меньше 100 КБ или доступно менее 200 КБ). Общее предположение состоит в том, что это будет происходить не очень часто... но, судя по тому, что я видел, устройства на базе Arduino в целом, которые используют Wi-Fi практически для чего угодно, имеют тенденцию надежно выходить из строя через несколько недель, если их не периодически перезагружать. .. так что я только начинаю с этого предположения и принимаю его :), @Bitbang3r

Что бы это ни стоило, у меня есть контроллер вентилятора на ATmega328p -> ESP-01 (прошивка AT), который работает непрерывно, пока сбой питания или какое-либо другое событие не отключит мою сеть Wi-Fi. Если бы было более важно поддерживать работу контроллера, его можно было бы заставить «не обращать внимания» на то, что Wi-Fi не работает, и просто продолжать работать без него. Wi-Fi предназначен только для того, чтобы я мог видеть, что делает контроллер, и не является необходимой функцией., @JRobert


0

Если вас это интересует, я создал библиотеку веб-сервера, которая не вообще используйте класс String.

Он декодирует входящие HTTP-запросы по одному элементу, передавая результаты в процедуру обратного вызова.

Таким образом, ему даже не нужно хранить весь HTTP-запрос в памяти, он декодирует отдельные параметры «на лету»; с помощью конечного автомата.

Поскольку динамическое распределение памяти отсутствует, теоретически вы сможете работать бесконечно.

Моя библиотека находится по адресу https://github.com/nickgammon/HTTPserver

Сказав это и ответив на ваш актуальный вопрос...


Динамическое распределение памяти не обязательно плохое. В частности, если объемы выделяемой памяти всегда одинаковы (например, вводимые вами данные на сервер предсказуемы), то память не должна исчерпаться. Распределитель будет продолжать выделять тот же бит памяти, который вы использовали в прошлый раз.

Что может быть особенно плохо, так это такие вещи:

String buf = "";
while (Serial.available ())
  {
  buf += Serial.read ();  // добавляем один байт
  }

Подобный код может вызвать фрагментацию кучи, поскольку он продолжает выделять все большие и большие фрагменты. Я не знаю, делает ли это упомянутая вами библиотека.


Обратите внимание: из вашего вопроса не совсем ясно, пишете ли вы HTTP клиент или сервер. Если вы пишете клиент, моя библиотека вам не поможет, но мои замечания все равно применимы.

,

Спасибо, но моя программа — это чисто http *клиент*. Главное, над чем я ломаю руки, это то, что основная задача схемы - «контролировать датчики влажности и включать пьезозуммер при обнаружении воды». Я отправляю рекламные объявления BLE для моего удобства отладки и время от времени делаю HTTP-запросы POST для регистрации данных и предоставления их мне доступными снаружи дома... но меня больше всего беспокоит то, чтобы сбои в работе Bluetooth или Wi-Fi не возникали. зависнуть или привести к сбою всей программы и вывести ее из строя от ее основной задачи (наблюдения за датчиками и зондирования пьезоэлемента, если необходимо)., @Bitbang3r

(продолжение)... Я *думаю*, что мне, возможно, придется в конечном итоге реализовать что-то, связанное со сторожевыми таймерами... но я не уверен, что в ESP32 вообще **есть** сторожевые таймеры, подобные AVR, способные автоматически перезагружать чип, если программное обеспечение не может «отметиться» в течение определенного периода времени. В любом случае это будет тема для другого вопроса ;-), @Bitbang3r

Согласно поиску в Google, у него действительно есть сторожевые таймеры., @Nick Gammon