Особенности освобождения памяти в MQL-программах

 

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

Я написал специальный тестовый скрипт и запустил его в отладке, что бы проконтролировать процесс освобождения памяти соответствующим оператором delete (все создаваемые объекты динамические). Ситуация не изменилась, освобождения памяти все равно не происходит:

//+------------------------------------------------------------------+
//|                                           TestMemoryFreeList.mq5 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#include  <Object.mqh>
#include  <Arrays\ArrayObj.mqh>

//#define ARRAY
class CData : public CObject
{
public:
   uchar DataArray[1024];
   CData()
   {
      ArrayInitialize(DataArray, 0x13);
   }
};
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   CArrayObj* list = new CArrayObj();
   //CList* list = new CList();
   for(int i = 0; i < 1000000; i++)
      list.Add(new CData());
   printf("Terminal used memmory: " + (string)TerminalInfoInteger(TERMINAL_MEMORY_USED));
   list.Clear(); // освобождаем память
   printf("After clear: " + (string)TerminalInfoInteger(TERMINAL_MEMORY_USED));
   delete list; // на всякий случай
}
//+------------------------------------------------------------------+

Размер памяти до и после вызова диструкторов в task menager: 

 

Соответственно встает вопрос, почему терминал не освобождает память?

Вначале думал, что это связано из-за фрагментации хранения элементов CList. Но замена на CArrayObj ничего не изменила. Возможно для MQL программ используется сборщик мусора и освобождение происходит не сразу, но запущенная более суток программа так и не освободила память. 

 
Да, сборщик мусора есть.

У нас как раз ведутся обсуждения по оптимизации работы с памятью.
 
Ilyas:
Да, сборщик мусора есть.

У нас как раз ведутся обсуждения по оптимизации работы с памятью.
Обсуждение это хорошо, но все-таки хотелось бы хоть какой-то реализации освобождения памяти.
 

Проблема в том, что Вы работаете в зацикленном скрипте.

Сборщик мусора отработает и вернёт память в систему, как только скрипт завершит работу.

 
Ilyas:

Проблема в том, что Вы работаете в зацикленном скрипте.

Сборщик мусора отработает и вернёт память в систему, как только скрипт завершит работу.

Я не работаю в зацикленном скрипте. В реальной задаче использую индикатор (без зацикливания). Но в нем точно также ничего не освобождается (уже больше суток работает, а используемая память все растет).
 
Vasiliy Sokolov:
Я не работаю в зацикленном скрипте. В реальной задаче использую индикатор (без зацикливания). Но в нем точно также ничего не освобождается (уже больше суток работает, а используемая память все растет).

Опишите пожалуйста подробнее свой индикатор

На нашем индикаторе данное поведение не воспроизводится:

#property indicator_chart_window
#property indicator_buffers 1
#include  <Object.mqh>
#include  <Arrays\ArrayObj.mqh>
//#define ARRAY
class CData : public CObject
  {
public:
   uchar             DataArray[1024];
                     CData()
     {
      ArrayInitialize(DataArray,0x13);
     }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnInit()
  {
   CArrayObj *list=new CArrayObj();
//CList* list = new CList();
   for(int i=0; i<1000000; i++)
      list.Add(new CData());
   printf("Terminal used memmory: "+(string)TerminalInfoInteger(TERMINAL_MEMORY_USED));
   list.Clear(); // освобождаем память
   printf("After clear: "+(string)TerminalInfoInteger(TERMINAL_MEMORY_USED));
   delete list; // на всякий случай   
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   return(rates_total);
  }
//+------------------------------------------------------------------+


Возможно Ваш индикатор активно работаем с различными символами?

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

  1. Индикатор не зациклен
  2. Было создано много объектов и после удалено
  3. Память не возвращается в систему
  4. Работы с символами нет
 
Сейчас попробовал составить тестовый пример на индикаторе - освобождение памяти сработало нормально. Буду разбираться в своем коде.
Причина обращения: