Управление памятью Arduino MKR WiFi 1010
Согласно официальной документации 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 с низким энергопотреблением»
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
- Защита SSL-сертификата Arduino MKR wifi 1010
- чтение свойств устройства или платы с устройства Arduino MKR WiFi 1010
- MKR 1010 WIFI Встроенный светодиод RGB не работает с BLE
- Падение напряжения при питании от батареек АА
- Почему сторожевой пес кусается слишком быстро?
- Проблема с сохранением значений из Arduino MKR 1010 в mysql?
- Отправить значения в arduino mkr 1010 из визуальной студии через Wi-Fi?
какая документация?, @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