Функция 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");      
}

, 👍0

Обсуждение

Учитывая ваш недавний поток похожих вопросов, которые меняют то, как компилятор управляет памятью, я **очень** рекомендую вам начать изучать основы сборки AVR, а затем _прочитать_ сборку, сгенерированную компилятором. Обещаю, это будет _просветительно_., @Edgar Bonet

Спасибо @Edgar за твое любезное предложение! :) Было бы здорово, если бы ты порекомендовал меня с какими-нибудь вескими рекомендациями... например, ссылками, книгами и т. д., @bandejiya


2 ответа


3

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

Компилятор достаточно умен. И в ядре AVR много регистров ЦП. Если для временной локальной переменной вроде этой есть свободный регистр, зачем тратить время и усилия на ее размещение в памяти, если можно просто сохранить ее в регистре?

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

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

,

Предположим, что процессор выбирает память для хранения переменной.. Разве переменная стека не будет занимать место после объявления?.. И свободная память должна быть уменьшена в функции jack относительно доступной памяти перед вызовом функции jack..?, @bandejiya

Процессор ничего не выбирает. Это решение принимает компилятор. Если он решает, что переменная используется только в течение короткого времени и есть свободный регистр, он выберет использование этого регистра вместо выделения места в стеке. Ваш взгляд на язык и компилятор слишком наивен., @Majenko

Извините..! Я новичок в UG.. все еще учусь.. :).. но предположим, что компилятор выбрал.. ! мой запрос, если он выбирает память для хранения переменной.. Разве переменная стека не будет занимать место после объявления..? И свободная память должна быть уменьшена в функции jack относительно доступной памяти перед вызовом функции jack..? (& Конечно, если эти переменные будут использоваться в некоторых условных операциях), @bandejiya

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


0

Функция 'jack' также не показывает никакой разницы в распределении. Поскольку jack() вызывается только в этом одном модуле (известно, потому что программа состоит только из одного модуля) и только один раз, компилятор может заменить вызов функции фактическим кодом функции, экономя как место, так и время вызова и возврата.

Эта оптимизация называется «встраиванием» (обычно полезно только в учебных целях, но обучение, похоже, является всей целью вашего наброска). Вы можете подавить встраивание, добавив к функции и ее объявлению префикс __attribute__ ((noinline)). (Обратите внимание, что этот атрибут специфичен для компиляторов gcc; другие компиляторы могут предоставлять другой способ сделать это или вообще не предоставлять):

__attribute__ ((noinline)) void jack();

...

__attribute__ ((noinline)) void jack(){
   ... etc ...
}
,