Функция freeMemory() из библиотеки memoryfree не возвращает уменьшенное значение в arduino UNO
Я сжег код, написанный ниже, я ожидаю, что, поскольку мы объявляем локальную переменную в цикле, функция freeMemory() должна возвращать уменьшенное значение. Но оно остается постоянным..! пожалуйста, объясните, почему..? Вывод прилагается:
#include <MemoryFree.h>
void setup()
{
// поместите сюда ваш код настройки для однократного запуска:
Serial.begin(9600); Serial.println(freeMemory(), DEC); // выводим объем доступной оперативной памяти.
Serial.println("Lets Start");
}
void jack();
void loop()
{
char c=0;
c++;
Serial.println("");
Serial.println("Rajat0");
Serial.println(freeMemory(), DEC);
Serial.println("Rajat1");
int x=0;
x++;
Serial.println("Rajat2");
Serial.println(freeMemory(), DEC);
Serial.println("Rajat3");
jack();
Serial.println("");
delay(1000);
}
void jack()
{
Serial.println("jack0");
int x=0;
x++;
Serial.println(freeMemory(), DEC);
Serial.println("jack1");
}
@bandejiya, 👍0
Обсуждение2 ответа
Вы предполагаете, что просто потому, что вы создали переменную, она будет сохранена в памяти. Это часто не так.
Компилятор достаточно умен. И в ядре AVR много регистров ЦП. Если для временной локальной переменной вроде этой есть свободный регистр, зачем тратить время и усилия на ее размещение в памяти, если можно просто сохранить ее в регистре?
Кроме того, поскольку вы на самом деле ничего не делаете с переменной, скорее всего, компилятор просто ее отбрасывает.
Обозначение переменной как volatile
устранит обе эти проблемы, и вы можете увидеть другие результаты.
Предположим, что процессор выбирает память для хранения переменной.. Разве переменная стека не будет занимать место после объявления?.. И свободная память должна быть уменьшена в функции jack относительно доступной памяти перед вызовом функции jack..?, @bandejiya
Процессор ничего не выбирает. Это решение принимает компилятор. Если он решает, что переменная используется только в течение короткого времени и есть свободный регистр, он выберет использование этого регистра вместо выделения места в стеке. Ваш взгляд на язык и компилятор слишком наивен., @Majenko
Извините..! Я новичок в UG.. все еще учусь.. :).. но предположим, что компилятор выбрал.. ! мой запрос, если он выбирает память для хранения переменной.. Разве переменная стека не будет занимать место после объявления..? И свободная память должна быть уменьшена в функции jack относительно доступной памяти перед вызовом функции jack..? (& Конечно, если эти переменные будут использоваться в некоторых условных операциях), @bandejiya
Если компилятор выбирает выделение памяти, то возможны два сценария. Либо память будет выделена в стеке в точке входа в функцию, либо она будет выделена при первом использовании переменной. Вам следует посмотреть на язык ассемблера, который выдает компилятор., @Majenko
Функция 'jack' также не показывает никакой разницы в распределении. Поскольку jack()
вызывается только в этом одном модуле (известно, потому что программа состоит только из одного модуля) и только один раз, компилятор может заменить вызов функции фактическим кодом функции, экономя как место, так и время вызова и возврата.
Эта оптимизация называется «встраиванием» (обычно полезно только в учебных целях, но обучение, похоже, является всей целью вашего наброска). Вы можете подавить встраивание, добавив к функции и ее объявлению префикс __attribute__ ((noinline))
. (Обратите внимание, что этот атрибут специфичен для компиляторов gcc; другие компиляторы могут предоставлять другой способ сделать это или вообще не предоставлять):
__attribute__ ((noinline)) void jack();
...
__attribute__ ((noinline)) void jack(){
... etc ...
}
- Библиотека MemoryFree, демонстрирующая нестандартное поведение..!
- Как очистить кучу памяти в esp32
- Последовательная печать из флэш-памяти (F() macro, PROGMEM, sprintf_P, SPTR)
- Помогите уменьшить размер скетча!
- Arduino записывает в память и автоматически выключается (через MOSFET)
- Включает ли скомпилированный бинарный файл скетча неиспользуемые функции из библиотеки?
- Приемлемо ли новое без удаления?
- Если код, используемый для ардуино, может быть встроен в постоянную вызываемую память, есть ли способ создать ОС для Arduino, которая запускается по вызову?
Учитывая ваш недавний поток похожих вопросов, которые меняют то, как компилятор управляет памятью, я **очень** рекомендую вам начать изучать основы сборки AVR, а затем _прочитать_ сборку, сгенерированную компилятором. Обещаю, это будет _просветительно_., @Edgar Bonet
Спасибо @Edgar за твое любезное предложение! :) Было бы здорово, если бы ты порекомендовал меня с какими-нибудь вескими рекомендациями... например, ссылками, книгами и т. д., @bandejiya