Управление памятью Arduino MKR WiFi 1010

mkr1010wifi arduino-mkr

Согласно официальной документации Arduino, память SRAM (отведенная для локальных переменных) должна автоматически освобождаться после вызова любой функции. Например, у меня есть функция memory_allocate_test2, которая объявляет большой массив символов, и эта функция вызывается в цикле(). Я ожидаю, что каждый раз после выполнения функции memory_allocate_test2 память SRAM, которую я выделил для локальных переменных внутри этой функции, должна быть освобождена или освобождена. Однако это не работает так. Когда я вызываю эту функцию в цикле(), микроконтроллер зависает и перестает работать, поскольку у него заканчивается доступная память SRAM. Позвольте мне привести пример кода:

void setup() {
  //Инициализируем последовательный порт и ждем открытия порта:
  Serial.begin(9600);
  
  while (!Serial) {
    ; // ждем подключения последовательного порта. Требуется только для собственного USB-порта — режим разработки. Его необходимо удалить при выпуске вживую!!!
  }
}

void loop() {
  delay(2000);
  memory_allocate_test2();
}

void memory_allocate_test2() {
  Serial.println("memory_allocate_test2 STARTING ");
  display_freeram();
  Serial.println("------------------------------------------------------------");
  Serial.println("Allocating the memory for the MKR: ");
  char* memory_usage_test = new char[2000];
  Serial.println("Allocated memory!");
  display_freeram();
  Serial.println("------------------------------------------------------------");
}

extern "C" char* sbrk(int incr);

void display_freeram(){
  Serial.print(F("- SRAM left: "));
  Serial.println(freeRam());
}

int freeRam() {
  char top;
  return &top - reinterpret_cast<char*>(sbrk(0));
}

почему это не работает так, как указано в документации? что я делаю не так? почему память SRAM не освобождается каждый раз после выполнения функции memory_allocate_test2?

https://www.seeedstudio.com/ blog/2021/04/26/managing-arduino-memory-flash-sram-eeprom/

Когда я выполняю эту программу, происходит вот что:

memory_allocate_test2 НАЧИНАЕТСЯ

  • Осталось SRAM: 7163

Выделение памяти для MKR: Выделенная память!

  • Осталось SRAM: 5155

memory_allocate_test2 НАЧИНАЕТСЯ

  • Осталось SRAM: 5155

Выделение памяти для MKR: Выделенная память!

  • Осталось SRAM: 3147

memory_allocate_test2 НАЧИНАЕТСЯ

  • Осталось SRAM: 3147

Выделение памяти для MKR: Выделенная память!

  • Осталось SRAM: 1139

memory_allocate_test2 НАЧИНАЕТСЯ

  • Осталось SRAM: 1139

Выделение памяти для MKR: Выделенная память!

  • Осталось SRAM: -869

memory_allocate_test2 НАЧИНАЕТСЯ

  • Осталось SRAM: -869

Выделение памяти для MKR:

в этот момент устройство просто зависает и перестает работать. Это не то, чего я ожидаю!

поскольку функциональность различается для каждой платы и микроконтроллера, вот мои характеристики: название платы: «Arduino® MKR WiFi 1010», имя микроконтроллера: «SAMD21 Cortex®-M0+ 32-битный микроконтроллер ARM с низким энергопотреблением»

, 👍0

Обсуждение

какая документация?, @Juraj

не микроконтроллер управляет выделением и освобождением памяти... это делает программа... кроме того, не существует такого понятия, как микроконтроллер Arduino, @jsotola

также задан вопрос https://forum.arduino.cc/t/arduino-mkr-wifi-1010-memory-management/1174122., @Juraj

@Juraj Единственная статья документации о структуре памяти и управлении MKR WiFi 1010, которую я нашел, представлена в вопросе выше. Не могли бы вы указать мне на официальную документацию, потому что я видел очень много разных статей и примеров, которые часто говорят разное., @Semen Shekhovtsov

@jsotola, верно, извините за ошибку, название платы — «Arduino® MKR WiFi 1010», имя микроконтроллера — «SAMD21 Cortex®-M0+ 32-битный ARM MCU с низким энергопотреблением». Я обновил содержание вопроса., @Semen Shekhovtsov


1 ответ


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

1

Вы смешиваете два разных способа распределения памяти.

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

void memory_allocate_test3() {
  Serial.println("memory_allocate_test3 STARTING ");
  display_freeram();
  Serial.println("------------------------------------------------------------");
  Serial.println("Allocating the memory for the MKR: ");
  char memory_usage_test[2000] = "Some content...";
  Serial.println("Allocated memory!");
  display_freeram();
  Serial.println("------------------------------------------------------------");
}

Но вы используете память, выделенную в куче из-за оператора new. За такое распределение полностью отвечает программист, то есть вы. Поскольку вы только выделяете и никогда не освобождаете, каждый цикл уменьшает оставшуюся оперативную память. Используйте delete (на самом деле delete[]), чтобы освободить:

void memory_allocate_test2() {
  Serial.println("memory_allocate_test2 STARTING ");
  display_freeram();
  Serial.println("------------------------------------------------------------");
  Serial.println("Allocating the memory for the MKR: ");
  char* memory_usage_test = new char[2000];
  Serial.println("Allocated memory!");
  display_freeram();
  Serial.println("------------------------------------------------------------");
  delete[] memory_usage_test;
}

Осторожно: существуют разные методы распределения: malloc/calloc/alloca/free и новый/удалить. Первый метод использует функции стандартной библиотеки C, второй метод использует ключевые слова C++.

Указатели, возвращаемые разными методами, несовместимы. Вы не можете освободить память с помощью free, которую вы выделили с помощью new. То же самое справедливо и для delete/malloc.

Однако вы можете использовать оба метода в одной программе.

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

Кстати, C и C++ — разные языки, хотя вы можете создать смешанную программу.

,

это то же самое, что вызов free(memory_usage_test)? Где-то во время исследования я увидел, что не рекомендуется использовать функции malloc(...) и free(...) для MKR WiFi 1010, знаете ли вы что-нибудь об этом? Этот вопрос возникает, потому что я использую в своем коде некоторые классы, которые внутренне используют функции malloc(...) и free(...)`., @Semen Shekhovtsov

Смотрите расширенный ответ., @the busybee