Проблема с объемом памяти в структуре

Я работаю над проектом, в котором мне нужно создать ИК-программу, которая работает со всеми платами AVR/Arduino для управления ИК-устройствами, такими как телевизор, DVD и т. д. Я создаю структуру, которая может нести Pronto информация о коде, и это то, что у меня есть до сих пор:

struct Pronto {
    char* code;
public:
    Pronto(){}
    Pronto(char* code) {
        bool isValid = validateProntoCode(code);
        if(isValid)
            this->code = code;
    }
    Pronto toPronto(char* code) {
        Pronto cde(code);
        return cde;
    }
    void setPronto(char* code){
        bool isValid = validateProntoCode(code);
        if(isValid)
            this->code = code;
    }
    char* toString(){
        return code;
    }
    private:
    bool validateProntoCode(char* code) {
        if(!isInHex(code[strlen(code)-1]))
            return false;
        for (int i = 0; i < strlen(code); i++) {
            if (!isInHex(code[i]) && !(i % 5 == 4 ))
                return false;
            if (i % 5 == 4 && code[i] != ' ')
                return false;
            if (i % 5 == 0 && (!isInHex(code[i]) || !isInHex(code[i] + 1) || !isInHex(code[i] + 2) || !isInHex(code[i + 3])))
                return false;
        }
        return true;
    }
    bool isInHex(char c) {
        char list[22] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'};
        for (int i = 0; i < 22; i++) {
            if (c == list[i])
                return true;
        }
        return false;
    }
};

Этот код структуры Я могу установить код Pronto, проверить его и получить из него строковое значение. Теперь всякий раз, когда я объявляю структуру внутри Arduino IDE:

pronto.setPronto("0000 006D 0000 00BF 009F 0031 0030 0010 0010 0031");

Я получаю следующее сообщение:


Sketch использует 4082 байта (12%) места для хранения программ. Максимальный размер – 32 256 байт.

Глобальные переменные используют 2137 байт (104 %) динамической памяти, а для локальных переменных остается -89 байт. Максимальный размер – 2048 байт.

Недостаточно памяти; см. http://www.arduino.cc/en/Guide/Troubleshooting#size советы по уменьшению ваш след.


Изображения:

https://prnt.sc/ohu4d9

https://prnt.sc/ohu4io

https://prnt.sc/ohu4m8

https://prnt.sc/ohu4pr

https://prnt.sc/ohu4tn

По сути, я просто показал всю свою работу над кодом, который я сделал. Я закомментировал все глобальные вары, ничего не изменилось. НО, когда я комментирую "pronto.setPronto("0000 0000");", я получаю свободное место.


Итак, как я могу изменить эту структуру, чтобы она не занимала много места?


Правильный код char*? Это проблема. Теперь вы можете помочь мне изменить код или, по крайней мере, сказать мне, как я могу решить эту проблему.

, 👍-1

Обсуждение

Сама структура не занимает много места, я вижу в основном сам код с 40 байтами. В сообщении говорится, что ваши глобальные переменные занимают 104% памяти. Проблема есть, но вы не показали нам свои глобальные переменные. Может быть, вы можете уменьшить количество глобальных переменных, когда их не нужно объявлять во время выполнения всей программы., @chrisl

Я сделал. Когда я закомментирую "pronto.setPronto("0000 0000");", я получаю больше свободного места. Но все #define, #include и другие глобальные переменные, которые я закомментировал, ничего не изменилось. Я собираюсь добавить URL-адрес с фотографиями в пост, чтобы показать вам., @Alex Zhuravel

Эм, а какой длины там протокод? Это определенно намного длиннее, чем в вашем вопросе., @chrisl

Это не имеет значения, код Pronto может быть сколь угодно длинным. Вы знаете, что это правильно? Все, что я сделал, это сохранил строку кода Pronto в переменной char*. Я не мог использовать строку или ее библиотеку, так как заголовок не позволял мне. В итоге я использовал char*., @Alex Zhuravel

Вы храните код в глобальной переменной, так что да, имеет значение, насколько он велик. У вас есть только 2 КБ, @chrisl


2 ответа


0

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

Код:

struct Pronto {
    char* code;
  public:
    Pronto() {}
    Pronto(char* code) {
      bool isValid = validateProntoCode(code);
      if (isValid)
        this->code = code;
    }
    Pronto toPronto(char* code) {
      Pronto cde(code);
      return cde;
    }
    void setPronto(char* code) {
      bool isValid = validateProntoCode(code);
      if (isValid)
        this->code = code;
    }
    char* toString() {
      return code;
    }
  private:
    bool validateProntoCode(char* code) {
      if (!isInHex(code[strlen(code) - 1]))
        return false;
      for (int i = 0; i < strlen(code); i++) {
        if (!isInHex(code[i]) && !(i % 5 == 4 ))
          return false;
        if (i % 5 == 4 && code[i] != ' ')
          return false;
        if (i % 5 == 0 && (!isInHex(code[i]) || !isInHex(code[i] + 1) || !isInHex(code[i] + 2) || !isInHex(code[i + 3])))
          return false;
      }
      return true;
    }
    bool isInHex(char c) {
      char list[22] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f'};
      for (int i = 0; i < 22; i++) {
        if (c == list[i])
          return true;
      }
      return false;
    }
};


Pronto pronto;

void setup() {
  pronto.setPronto("0000 006D 0000 00BF 009F 0031 0030 0010 0010 0031");
}

void loop() {}

Процедура проверки для ATmega328P возвращает:

D:\Extra\Arduino\BatteryRestorer\BatteryRestorer.ino: In function 'void setup()':

D:\Extra\Arduino\BatteryRestorer\BatteryRestorer.ino:50:71: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

   pronto.setPronto("0000 006D 0000 00BF 009F 0031 0030 0010 0010 0031");

                                                                       ^
Sketch uses 844 bytes (2%) of program storage space. Maximum is 30720 bytes.
Global variables use 83 bytes (4%) of dynamic memory, leaving 1965 bytes for local variables. Maximum is 2048 bytes.

Можете ли вы проверить, сохраняется ли проблема с этим скетчом файла? Возможно, вы установили и связали библиотеку, которая выделяет много глобальных переменных.

,

1

На снимках экрана вы используете строковые литералы, которые намного длиннее, чем в вашем примере кода. Я подозреваю, что использование PROGMEM может быть способом обойти проблему. Но зачем возиться с постоянными строками, проверять и преобразовывать их во время выполнения, а не хранить их как необработанные данные? (Кроме того, результат проверки константного строкового литерала всегда будет одним и тем же. Поэтому рассмотрите возможность удаления проверки вашего производственного кода.)

uint16_t myParsedProntoCode[] = {
    0x0000, 0x006D, 0x0000, 0x00BF, 0x009F, 0x0031, 0x0030, 0x0010, 0x0010, 0x0031
};

Это намного эффективнее, так как для хранения полубайта (4 бита) требуется всего 4 бита вместо 8 бит. Так что только половина пробела, даже не принимая во внимание бессмысленные пробелы.

,

Большое спасибо, теперь он экономит больше места., @Alex Zhuravel