«Безопасно» ли использовать ключевое слово «new» для создания экземпляров нескольких сенсорных объектов?

Я читал, что использование динамического распределения памяти в микроконтроллере является плохой практикой, и я вполне понимаю, почему.

>

Я разрабатываю специальную печатную плату на базе ATMega2560, и в моей ситуации мне нужно создать 24 объекта для одного типа датчиков и еще 8 для еще.

При небольшом количестве датчиков вы можете создавать такие объекты:

Ezo_board PH = Ezo_board(99, "PH");       //создаем объект цепи PH с адресом 99 и именем "PH"
Ezo_board EC = Ezo_board(100, "EC");      //создаем объект схемы EC с адресом 100 и именем "EC"

Но поскольку у меня их так много, и я хочу просмотреть их, я создал массив указателей Ezo_board *EC[maxEC];

и в функции настройки я написал:

for (uint8_t i = 0; i < maxEC; i++)
 {
  EC[i] = new Ezo_board(i+11) //передача адреса I2C, который начинается с 11 и увеличивается

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

, 👍0

Обсуждение

Как вы думаете, зачем вам динамическое размещение? Это может быть Ezo_board boards[] = {{99,"PH"}, {100,"EC"}, };, или, если у него неоднозначные конструкторы, вам понадобится = {Ezo_board(99, "PH" ), Ezo_board(100, "EC"), }, @KIIV

Меня беспокоило жесткое кодирование всех датчиков, когда я мог захотеть отрегулировать количество датчиков, используемых на данной плате. Определив количество датчиков (maxEC), мне просто нужно изменить константу., @MattD

Ну, Arduino какое-то время поддерживает стандарт C++11, вы можете использовать цикл for на основе диапазона, например: for (auto & Sensor : Sensors) { ... и вам не обязательно знать размер, @KIIV

Раньше я не слышал о циклах на основе диапазона, я поищу это!, @MattD


2 ответа


Лучший ответ:

0

Опасность использования динамической памяти на встроенных устройствах заключается в повторяющемся выделении и amp; дераспределение фрагментов памяти. Распределитель памяти выделяет часть памяти для каждого выделения. Когда один возвращается, дераспределитель объединяет его (или должен объединить) с соседним свободным чаном, если он есть, чтобы создать больший свободный фрагмент вместо двух соседних меньших. Но это большое «если»: 1) пытается ли конкретный менеджер памяти вообще это сделать? и 2) во многих случаях это даже невозможно.

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

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

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

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

,

0

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

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

Я регулярно делаю подобные вещи, и у меня нет с этим проблем.

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

Существует множество правил, как сделать код лучше, и после каждого из них есть какая-то причина. Но некоторые идут против других.

У меня есть Arduino для развлечения, и я использую правила в качестве рекомендаций, но я — хозяин своего кода. Поэтому иногда я иду другим путем.

Если это поможет мне лучше организовать код, у меня не возникнет проблем сделать все по-своему.

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

При домашней разработке я делюсь кодом в основном с самим собой, и мне не платят. Так что мне приходится заботиться в основном только о себе будущем)

,