Как расходуется память при многократном пересоздании массива в цикле?

 

Наверное глупый вопрос, но все же рискну спросить. Что происходит с памятью, если использовать вот такой код:

   int i=0;

   while(i<5000)
     {
      i++;
      int array[1000];
     }

Созданный на предыдущей итерации массив выгружается с памяти или для нового массива просто выделяется новая память и теоретически мы можем ее перезаполнить?

И это какая используется память: RAM?

 
leon_17:

Наверное глупый вопрос, но все же рискну спросить. Что происходит с памятью, если использовать вот такой код:

Созданный на предыдущей итерации массив выгружается с памяти или для нового массива просто выделяется новая память и теоретически мы можем ее перезаполнить?

И это какая используется память: RAM?

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

 
Ihor Herasko:

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

В си массив находится постоянно на стеке, ничего не выделяется и не освобождается. Но вот Как реализовано в мкл - могут ответить только разработчики.
 
SeriousRacoon:
В си массив находится постоянно на стеке, ничего не выделяется и не освобождается. Но вот Как реализовано в мкл - могут ответить только разработчики.

Почему же тогда при очередной итерации там обнаруживаются совершенно не те данные, которые были на предыдущей итерации? Неужели кто-то без нашего ведома постоянно инициализирует эту память?

 
Ihor Herasko:

Почему же тогда при очередной итерации там обнаруживаются совершенно не те данные, которые были на предыдущей итерации? Неужели кто-то без нашего ведома постоянно инициализирует эту память?

Так стек же. Мало ли что код, сгенерированный компилятором, туда придумает поназаписывать. Данные валидны только от объявления до закрытия области видимости (обычно "}").
 
leon_17:

Наверное глупый вопрос, но все же рискну спросить. Что происходит с памятью, если использовать вот такой код:

Созданный на предыдущей итерации массив выгружается с памяти или для нового массива просто выделяется новая память и теоретически мы можем ее перезаполнить?

И это какая используется память: RAM?

Просто не пишите так и все. По крайней мере, можно убедиться, что скорость ниже, по сравнению с объявленем массива перед циклом.

 
Dmitry Fedoseev:

Просто не пишите так и все. По крайней мере, можно убедиться, что скорость ниже, по сравнению с объявленем массива перед циклом.

тестировать не буду, не интересно

но помню в справке(или кто то из разработчиков писал) было написано, что статические массивы ограничены по размеру и создаются в другом участке памяти

у топикстартера статистически распределенный массив - в справке про них что то не нашел описания, а про динамические массивы:

Динамические массивы автоматически освобождаются при выходе за пределы области видимости блока, в котором они объявлены.

https://www.mql5.com/ru/docs/basis/types/dynamic_array

компилятор MQL очень хорошо оптимизирует код, в общем просто нужно проверить скорость работы

 
Igor Makanu:

тестировать не буду, не интересно

но помню в справке(или кто то из разработчиков писал) было написано, что статические массивы ограничены по размеру и создаются в другом участке памяти

у топикстартера статистически распределенный массив - в справке про них что то не нашел описания, а про динамические массивы:

https://www.mql5.com/ru/docs/basis/types/dynamic_array

компилятор MQL очень хорошо оптимизирует код, в общем просто нужно проверить скорость работы

С массивом не проверял скорость, но с одной переменной проверял, когда снаружи цикла объявлена, быстрее работает.

 
Dmitry Fedoseev:

Просто не пишите так и все. По крайней мере, можно убедиться, что скорость ниже, по сравнению с объявленем массива перед циклом.

А если вначале цикла на каждой итерации нужен чистый массив (для сбора неких значений на основании неких изменяющихся данных в условии массива)?

Igor Makanu:

Динамические массивы автоматически освобождаются при выходе за пределы области видимости блока, в котором они объявлены.

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

   int i=0;
   
   while(i<500)
     {
      i++;

      int array[];

      ArrayResize(array,i+100);
     }

 
leon_17:

Область видимости здесь тело цикла, я правильно понимаю? Пример кода:

область видимости ровно то, что записано между {   }

скрипт для проверки:

void OnStart()
{
   {
      int a;
      a = 5;
   }
   Print("a = ", a);     //'a' - undeclared identifier
}
leon_17:

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

то есть получается ровно то, что Вы написали в коде:

{
  i++;                                  // 1. инкремент i
  int array[];                          // 2. объявление массива
  ArrayResize(array,i+100);             // 3. выделение памяти массиву
}

пп 1,2,3 выполняете в цикле 500 раз, т.е. каждый раз инкремент и  каждый раз выделение памяти, обьявления переменных не требуют времени при выполнении, это будет произведено при входе в область локальной видимости - принцип как и в теле функций.

Другой вопрос, замерить производительность кода в первом сообщении, ну а Ваш последний код будет постоянно терять производительность из за ArrayResize()

 

замерил скорость:

#property strict
#property script_show_inputs
// количество итераций теста
#define LOOPx10 7

#define   SpeedTest(count_x10,msg,EX)        {uint mss=GetTickCount(); ulong count=(ulong)pow(10,count_x10);for(ulong ii=0;ii<count&&!_StopFlag;ii++){EX;} \
                                              printf("%s: loops=%i ms=%u",msg,count,GetTickCount()-mss);}
//+------------------------------------------------------------------+
void OnStart()
{
// tst 1
   SpeedTest(
   LOOPx10,"Test №1 = ",
   {
      int i = 1;
      while(i < 1000)
      {
         int array[1000];
         array[i] = rand() % i;
         i++;
      }
   }
   )
   
// tst 2   
   SpeedTest(
   LOOPx10,"Test №2 = ",
   {
      int i = 1;
      int array[1000];
      while(i < 1000)
      {
         array[i] = rand() % i;
         i++;
      }
   }
   )
}

2020.03.02 22:40:21.269 tst (EURUSD,H1) Test №1 = : loops=10000000 ms=15938

2020.03.02 22:40:37.179 tst (EURUSD,H1) Test №2 = : loops=10000000 ms=15906


т.е. варианты 1 и 2 по скорости выполнения по сути одинаковы