MQL5: Why is this code causing a massive memory leak?

 

This code is consuming memory like a black hole. It runs up to 10GB RAM within 10 seconds of running.

I don't quite understand why. I reserve memory for the arrays, I create 2 MAs, CopyBuffer, then release the MAs aswell as the arrays. This does not happen when I comment out the "CopyBuffer( ... )" calls. Any idea why and how to fix this?

Showcase:

//+------------------------------------------------------------------+
//|                                                     LeakTest.mq5 |
//|                                            Copyright 2020, mw108 |
//|                                                mwfx108@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, mw108"
#property link      "mwfx108@gmail.com"
#property version   "1.00"

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| CopyBuffer function                                              |
//+------------------------------------------------------------------+
void DoCopyBuffer( int i, int j, int k, int l, int c )
{
   // Allocate memory for array
   double ma[], ma2[];
   ArrayResize( ma, c );
   ArrayResize( ma2, c );
   
   // Create a Moving Average Indicators
   int maHandle = iMA( _Symbol, _Period, i, j, MODE_EMA, PRICE_CLOSE );
   int maHandle2 = iMA( _Symbol, _Period, k, l, MODE_EMA, PRICE_CLOSE );
   
   // Copy data from the MAs
   CopyBuffer( maHandle, 0, 1, c, ma );
   CopyBuffer( maHandle2, 0, 1, c, ma2 );
   
   // Release Moving Average
   IndicatorRelease( maHandle );
   IndicatorRelease( maHandle2 );
   
   // Free memory of array
   ArrayFree( ma );
   ArrayFree( ma2 );
}
//+------------------------------------------------------------------+
//| Test function                                                    |
//+------------------------------------------------------------------+
void DoTest()
{
   for ( int i = 13; i < 21; i++ )
   {
      for ( int j = 0; j < 6; j++ )
      {
         for ( int k = 34; k < 89; k++ )
         {
            for ( int l = 0; l < 6; l++ )
            {
               int c = 1 + MathRand() % 100;
               PrintFormat( "DoTest: %d, %d, %d, %d, %d", i, j, k, l, c );
               DoCopyBuffer( i, j, k, l, c );
            }
         }
      }
   }
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

   // Only do once per bar
   static datetime _lastBarTime = 0;
   datetime currentBarTime = iTime( _Symbol, _Period, 0 );
   if ( currentBarTime <= _lastBarTime )
      return;
   _lastBarTime = currentBarTime;
   
   DoTest();   
//---   
  }
//+------------------------------------------------------------------+
 
mwfx108: This code is consuming memory like a black hole. It runs up to 10GB RAM within 10 seconds of running.
   for ( int i = 13; i < 21; i++ )
   {
      for ( int j = 0; j < 6; j++ )
      {
         for ( int k = 34; k < 89; k++ )
         {
            for ( int l = 0; l < 6; l++ )
            {
               
               DoCopyBuffer( i, j, k, l, c );

There is no memory leak. You are loading (21-13)*6 + (89-34)*6 = 378 different indicators on each new bar. Why are you surprised. Each will be unloaded ten minutes after the last access.

 
William Roeder:

There is no memory leak. You are loading (21-13)*6 + (89-34)*6 = 378 different indicators on each new bar. Why are you surprised. Each will be unloaded ten minutes after the last access.

Oh really. D: Thanks for the invaluable information! I assumed that IndicatorRelease unloads the indicator and releases the memory. Is there any way to unload / free it?

Edit: The creation of the indicators isn't the problem though. It is only when using CopyBuffer( ... ) that the massive memory consumption begins.
Edit2: Hmm, I see. IndicatorRelease isn't executed in StrategyTester ... :/
The handle is removed immediately, the calculation block is deleted in some time (if it's not called anymore). When working in the strategy tester, the IndicatorRelease() function is not executed.