Объявить глобальную переменную в функции

VadimKHL
Offline
Зарегистрирован: 19.10.2020

Добрый вечер!

Задача такая, я считываю в цикле SETUP() размер массива из EEPROM.

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

rkit
Offline
Зарегистрирован: 23.11.2016

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

VadimKHL
Offline
Зарегистрирован: 19.10.2020

Печально(

Гриша
Offline
Зарегистрирован: 27.04.2014

rkit пишет:

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

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

rkit пишет:

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

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

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

А в чем проблема-то


byte * buf;

void setup() {
  unsigned int bufSize;
  //получаем размер буфера откуда-нибудь
  buf = (byte*) malloc(bufSize);
  if (buf == NULL)
  {
      //Увы, нужного количества свободной памяти нет. Вешаемся... 
  }

}

void loop() {
  buf[0]=23;

}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

asam пишет:

А в чем проблема-то


byte * buf;

void setup() {
  unsigned int bufSize;
  //получаем размер буфера откуда-нибудь
  buf = (byte*) malloc(bufSize);
  if (buf == NULL)
  {
      //Увы, нужного количества свободной памяти нет. Вешаемся... 
  }

}

void loop() {
  buf[0]=23;

}

так это из кучи и получается

Гриша
Offline
Зарегистрирован: 27.04.2014

VadimKHL пишет:

Далее, ... с требуемым размером, что бы он был глобальным

и куда ползти будет наш массив? был вариант, кода такие массивы указывали в конце памяти так сказать, ползет пока место есть. Не помню, чтоб такие решения пользовались популярностью.

гораздо проще, сразу выделить, все что не занял код, а потом просто не использовать лишнее от массива.

т.е. просто засунуть размер в переменную которая ограничит наш массив в коде.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

ua6em пишет:

так это из кучи и получается

Ну так и в чем проблема-то? Какая разница - что из кучи, что статически, все равно из того же самого ОЗУ выделяться будет.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

VadimKHL пишет:

Добрый вечер!

Задача такая, я считываю в цикле SETUP() размер массива из EEPROM.

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

Нахрена?  Если массив не расширяется, оставь его в EEPROM и читай оттуда. 

Да даже если и расширяется, тоже оставь. Тока не пиши в него слишком часто. 

VadimKHL
Offline
Зарегистрирован: 19.10.2020

asam пишет:

А в чем проблема-то


byte * buf;

void setup() {
  unsigned int bufSize;
  //получаем размер буфера откуда-нибудь
  buf = (byte*) malloc(bufSize);
  if (buf == NULL)
  {
      //Увы, нужного количества свободной памяти нет. Вешаемся... 
  }

}

void loop() {
  buf[0]=23;

}

 

Спасибо! Познакомился с динамической памятью.

rkit
Offline
Зарегистрирован: 23.11.2016

asam пишет:

ua6em пишет:

так это из кучи и получается

Ну так и в чем проблема-то? Какая разница - что из кучи, что статически, все равно из того же самого ОЗУ выделяться будет.

Потому что просто не нужно. Потому что ты дал более сложную вещь и не научил как освобождать и как работать размером, то есть любезно разложил грабли.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

rkit пишет:

Потому что просто не нужно. Потому что ты дал более сложную вещь и не научил как освобождать и как работать размером, то есть любезно разложил грабли.

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

rkit
Offline
Зарегистрирован: 23.11.2016

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

asam пишет:

rkit пишет:

Потому что просто не нужно. Потому что ты дал более сложную вещь и не научил как освобождать и как работать размером, то есть любезно разложил грабли.

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

скорее всего никак, но в этом случае память отгрызается снизу, оставляя какое-то количество на стек, в противном случае память растёт вниз, отгрызая от стека и нет никакой уверенности, что даже если её хватило, в работающем коде стек не пересечёт границу (не залезет в память переменных), то-есть совсем никакой, на асме я это контролировал ручками не допуская неконтролируемой рекурсии, да и программки были мелкие от пару-тройку десятков байт до 3-5 килобайт, а памяти вагон - 64кб

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

rkit пишет:

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

Да познания блещуть....

Какие байты тебе не нужно считать?

А размерность - ну так объявляй нужную размерность и работай себе спокойно. Никто не обосрется. Ну разве что ты. 

rkit
Offline
Зарегистрирован: 23.11.2016

Понятно, сам не знаешь, а других учишь. Стандарт. Ладно, ликбез.

Вот так это делается, если ты застрял в 85м: uint32_t * arr = malloc(n * sizeof(uint32_t));.

Вот этак это делается, если ты знаешь язык на котором программируешь: auto arr = new uint32_t[n]();

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

rkit пишет:

auto arr = new uint32_t[n]();

А круглые скопки зачем?  Вот так не работает? 

uint32_t *arr = new uint32_t[n];

Есть какой то нюанс?  

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

rkit пишет:

auto arr = new uint32_t[n]();

А круглые скопки зачем?  Вот так не работает? 

uint32_t *arr = new uint32_t[n];

Есть какой то нюанс?  

а так нельзя?
uint24_t *arr = new uint24_t[n];

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

1. Асам написал всё верно, естественно. Можно и так и иначе выделить память на куче. Это нормально, правильно и удобно. Тип указателя нужно привести к требуемому.

2. Есть одно "но". Несмотря на порядком задолбавшее хамство Ркит-а, есть резон и в его реплике. В том смысле, что в ембед-системах нет никакого резона так поступать. Допустим мы выделили не максимум памяти, а столько, сколько реально нужно массиву и было записано в ЕЕПРОМ. С сэкономленной  памятью что делать будем? На привозе торговать?

Тут смысл в принципиальном отличии программирования компа и контроллера. Некуда в контроллере использовать случайно свободную память. В нем работает одна программа, та, что автор написал, и не может быть ситуации в которой память, свободная от одного объекта, будет использована с выгодой другим.

Вернее сказать так: я могу написать такой код, который будет полезным образом использовать разное количество памяти, Женя сможет, ну еще пара человек на форуме смогут  так написать, но это будет не реальная задача, а так - баловство шаловливого ума.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

wdrakula - ты другое подскажи, как отслеживать требуемую глубину стека, чтобы не напороться на пересечение

b707
Offline
Зарегистрирован: 26.05.2017

wdrakula пишет:

2. Есть одно "но". Несмотря на порядком задолбавшее хамство Ркит-а, есть резон и в его реплике. В том смысле, что в ембед-системах нет никакого резона так поступать. Допустим мы выделили не максимум памяти, а столько, сколько реально нужно массиву и было записано в ЕЕПРОМ. С сэкономленной  памятью что делать будем? На привозе торговать?

тут не соглашусь. Если мы пишем программу, которая должна обрабатывать данные максимально возможного обьема, то в этом случае идея заранее выделить максимум доступной памяти как статичесий массив не работает. Точнее работает, но несет кучу гемора для разработчика - по мере разработки основного кода ему придется постоянно пересчитывать размер свободной памяти и корректировать размер статического массива. Значительно удобнее занимать весь обьем доступной памяти динамически в ходе работы конкретной версии программы.

В связи с этим два вопроса

 - есть ли в микроконтроллерах способ в ходе выполнения запросить обьем свободной на данный момент памяти?

 - и точно такой же вопрос, но на этапе компиляции - можно ли как-то в конкретной строчке программы выяснить, что к этому моменту память, условно говоря. "вся разобрана"? :)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707 пишет:

В связи с этим два вопроса

 - есть ли в микроконтроллерах способ в ходе выполнения запросить обьем свободной на данный момент памяти?

Есть.  Петрович разъяснял и показывал как. Где-то в этюдах

Kakmyc
Offline
Зарегистрирован: 15.01.2018

b707 пишет:

wdrakula пишет:

2. Есть одно "но". Несмотря на порядком задолбавшее хамство Ркит-а, есть резон и в его реплике. В том смысле, что в ембед-системах нет никакого резона так поступать. Допустим мы выделили не максимум памяти, а столько, сколько реально нужно массиву и было записано в ЕЕПРОМ. С сэкономленной  памятью что делать будем? На привозе торговать?

тут не соглашусь. Если мы пишем программу, которая должна обрабатывать данные максимально возможного обьема, то в этом случае идея заранее выделить максимум доступной памяти как статичесий массив не работает. Точнее работает, но несет кучу гемора для разработчика - по мере разработки основного кода ему придется постоянно пересчитывать размер свободной памяти и корректировать размер статического массива. Значительно удобнее занимать весь обьем доступной памяти динамически в ходе работы конкретной версии программы.

В связи с этим два вопроса

 - есть ли в микроконтроллерах способ в ходе выполнения запросить обьем свободной на данный момент памяти?

 - и точно такой же вопрос, но на этапе компиляции - можно ли как-то в конкретной строчке программы выяснить, что к этому моменту память, условно говоря. "вся разобрана"? :)

 

 

В первом случае можно так узнать

int freeRam () { 
 extern int __heap_start, *__brkval; 
 int v; 
 return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

 

Гриша
Offline
Зарегистрирован: 27.04.2014

Вот дырявая у меня голова, от того и кодить человечески не умею... 100% помню, что пару лет назад был ровно такой-же топик (по смыслу) и результат дискуссии  был аналогичен. т.е.

wdrakula пишет:

Тут смысл в принципиальном отличии программирования компа и контроллера. Некуда в контроллере использовать случайно свободную память.

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

b707 пишет:

мы пишем программу, которая должна обрабатывать данные максимально возможного обьема, то в этом случае идея заранее выделить максимум доступной памяти как статичесий массив не работает. Точнее работает, но несет кучу гемора для разработчика - по мере разработки основного кода ему придется постоянно пересчитывать размер свободной памяти и корректировать размер статического массива. Значительно удобнее занимать весь обьем доступной памяти динамически в ходе работы конкретной версии программы.

В связи с этим два вопроса

 - есть ли в микроконтроллерах способ в ходе выполнения запросить обьем свободной на данный момент памяти?

 - и точно такой же вопрос, но на этапе компиляции - можно ли как-то в конкретной строчке программы выяснить, что к этому моменту память, условно говоря. "вся разобрана"? :)

1.про разработчика, который что-то пересчитывает - сорян, но это поток сознания. Какие максимальные данные??? Это контроллер, вашу...ть! Он диодиками моргает, свет включает, температуру поддерживает... и т.п. какие в ж... массивы данных неизвестного размера ему обрабатывать???

2. конечно есть! и не нужно Женю беспокоить.

#include <stdlib.h>
#include <alloca.h>

void setup() {
Serial.begin(115200);

}

void loop() {
  byte *Pstack = alloca(1);
  byte *Pheap = malloc(1);

  Serial.print("Heap 1st free addres is:");
  Serial.println((int) Pheap);

  Serial.print("Stack 1st free addres is:");
  Serial.println((int) Pstack);
  
  Serial.print("free mem is:");
  Serial.println((int) Pstack - (int) Pheap +1);

  delay(2000);

  

}

обращаю внимание, что стек не меняется, что очевидно, а куча уменьшается по 4 байта, а не по 1. если ОЧЕНЬ интересно - расскажу почему, а лучше сам узнай! ;))

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

rkit пишет:

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

Ну да, совет для эмбеда - самое то. Если ориентироваться на 328, то EEPROM'а у нее 1 кБайт, следовательно и массив нужно выделять 1 кБайт. Замечательное решение!

VadimKHL
Offline
Зарегистрирован: 19.10.2020

andriano пишет:

rkit пишет:

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

Ну да, совет для эмбеда - самое то. Если ориентироваться на 328, то EEPROM'а у нее 1 кБайт, следовательно и массив нужно выделять 1 кБайт. Замечательное решение!

ESP32

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

VadimKHL пишет:

ESP32

А если внешний EEPROM на 512к? А если это вообще не EEPROM, а SD?

В общем, если у Вас возникло желание поместить копию EEPROM в ОЗУ, это говорит об ошибке проектирования. 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

qwone пишет:

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

VadimKHL
Offline
Зарегистрирован: 19.10.2020

andriano пишет:

VadimKHL пишет:

ESP32

А если внешний EEPROM на 512к? А если это вообще не EEPROM, а SD?

В общем, если у Вас возникло желание поместить копию EEPROM в ОЗУ, это говорит об ошибке проектирования. 

Вы где нибудь видели, что я такое писал?

Есть настройка, храниться в EEPROM, какой глубиной требуется делать сглаживание термокадров.

В зависимости от этой настройки, нужно создавать массив uint32_t [X][32][32], X равный количества требуемых кадров для сглаживания.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

wdrakula пишет:

1.про разработчика, который что-то пересчитывает - сорян, но это поток сознания. Какие максимальные данные??? Это контроллер, вашу...ть! Он диодиками моргает, свет включает, температуру поддерживает... и т.п. какие в ж... массивы данных неизвестного размера ему обрабатывать???

Ну даже в случае поморгать и температуру поддерживать такая ситуация вполне может возникнуть.

Например есть датчики по которым нужно считать скользящее среднее по возможно бОльшему окну. Образовалось больше памяти - выделяем больше под буфера.

Или есть цветной дисплей с динамической индикацией. И вынь да полож ему экранный буфер. Но он может работать с разной глубиной цветности. Есть больше памяти - работаем с большим BPP 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

asam пишет:
Или есть цветной дисплей с динамической индикацией. И вынь да полож ему экранный буфер. Но он может работать с разной глубиной цветности. Есть больше памяти - работаем с большим BPP
Если для того что бы покупать ребенка в ванной нужен не маленький кораблик, а шестой авианосный флот, то купайте ребенка в бассейне. Так вы сбережете себе и ребенку нервы.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Скорее уж в океане... ))