1 глобальная переменная, потребляющая 19% памяти

Я работаю над простым проектом по общению с последовательным монитором, и моя единственная глобальная переменная (тип"int", называемый "incomingByte") потребляет много памяти. Нет никаких проблем с запуском scketch, но меня это не устраивает.

Когда я загружаю его, я получаю: "Глобальные переменные используют 390 байт (19%) динамической памяти...". Почему это происходит и как я могу это исправить?

int incomingByte = 0; //for the incoming serial data
void setup() {
  // put your setup code here, to run once:
  randomSeed(analogRead(0)); //starts the pseudo-random sequence in a random point
  Serial.begin(9600);
  //waits for serial initialization to send the messages:
  //(Serial) returns false for serial off, and true for serial on. This is inverted with !.
  while(!Serial){
    ;
  }
  //sending instructions:
  Serial.println("Initializing...");
  Serial.println(" ");
  delay(2000);
  Serial.println("Please select an option:");
  Serial.println("1 - greetings");
  Serial.println("2 - random number");
  Serial.println("3 - calculator");
  Serial.println(" ");
}

void loop() {
  // put your main code here, to run repeatedly:
  if(Serial.available() > 0){
    incomingByte = Serial.read(); // Serial.read() returns the first byte of incoming data
  
    //recognizing the command received:
    if (incomingByte == '1'){
      numberOne();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
    if (incomingByte == '2'){
      numberTwo();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
    if (incomingByte == '3'){
      numberThree();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
  }
}


void numberOne() {
  Serial.println("Hello, Vitor! Good to see you!");
}


void numberTwo() {
  //sets the random number to be picked between [0, 101[
  long randomNum = random(0, 101);
  Serial.print("Your random number is: ");
  Serial.println(randomNum, DEC);
}

void numberThree(){
  Serial.println("Tool not available yet");
}

, 👍1

Обсуждение

Почему вы думаете, что все динамическое распределение памяти предназначено для этой переменной? Другие вещи (например, Последовательный) также используют часть оперативной памяти, @chrisl

Я думаю, что это потому, что сообщение, которое я получаю, говорит о "Глобальных переменных". Как вы сказали, считается ли объект "Serial" глобальной переменной при использовании оперативной памяти?, @Vitor Z.

Да, это глобально. Он просто определен в другом файле (внутри используемого ядра Arduino), но там в глобальном масштабе, @chrisl

Случайное семя также должно быть где-то сохранено или какое-то другое состояние для ГСЧ., @Mat

Просто из любопытства, если у вас есть **две** глобальные переменные, используют ли они 38% памяти?, @Nick Gammon


1 ответ


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

7

Несколько вещей, которые относятся к “глобальным переменным”, о которых вы можете не думать:

  • все ваши литеральные строки, если только они не инкапсулированы в макрос F () ; у вас их довольно много
  • Последовательный объект, включая его буферы передачи и приема (157 байты на Uno)
  • vtable для HardwareSerial (это класс, к которому принадлежит Serial , 18 байт)
  • Переменные учета времени (9 байт).

Кроме того, существуют фактические глобальные переменные вашего кода и статические локальные переменные, которые для целей выделения памяти совпадают с глобальными. Например, int занимает 2 байта. AVR и 4 байта на большинстве других аппаратных платформ.


Edit: ответ на вопросы в комментарии

каждый раз, когда я вызываю Serial, это увеличивает потребление памяти кодом?

Я не совсем понимаю, что вы подразумеваете под “каждый раз”:

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

почему IDE рассматривает все, что использует ОЗУ, как глобальную переменную?

Когда он говорит “глобальные переменные”, он на самом деле означает “статически распределенные данные”. Он говорит “глобальные переменные”, потому что он ориентирован на начинающих, и авторы предполагают, что новички не поймут, что означает статическое распределение. Глобальные переменные-это простейшая форма статического распределения.

есть ли разница в потреблении между глобальными и местными жителями?

ДА. Глобальные переменные выделяются статически, то есть во время компиляции. Вот почему IDE может сообщить, сколько места они будут потреблять. Местные жители (по крайней мере, нестатические местные жители) выделяются и освобождаются в стеке во время выполнения. За исключением запуска программы в эмуляторе, очень трудно предсказать, сколько места в стеке будет потреблять программа, так как это обычно зависит от событий времени выполнения.

,

Я понял о буквальных строках и последовательном потреблении, но я не мог получить некоторые очки. Во-первых, каждый раз, когда я вызываю "Serial", это увеличивает потребление памяти кодом? Кроме того, почему IDE рассматривает все, что использует ОЗУ, как глобальную переменную? (есть ли разница в потреблении между глобальными и местными жителями?), @Vitor Z.

@VitorZ.: se расширенный ответ., @Edgar Bonet

О, теперь я понял! Ваше объяснение было очень полезным и полным, спасибо. Используя ваш совет при передаче строк в PROGMEM с помощью F(), я мог бы уменьшить потребление SRAM с 19% до всего лишь 9%, при этом использование Flash увеличилось всего на 1%., @Vitor Z.