mql4mql5

Why memory leaks with a dynamic array of a custom class?


I'm creating a indicator that recognizes candlestick shapes.

To do that I created a separate class Candlestick that I include to the indicator file.

The problem is that I suffer from memory leaks.

I'm new to pointers and after reading / watching a lot, I still seem to miss something here.

This is the Indicator class. The content of the Candlestick class is irrelevant so I leave that out.

Candlestick *candles[]; 

void OnDeinit(const int reason)
{
    for(int i = 0; i < ArraySize(candles); i++ ){
      delete(candles[i]);
    }
}

int OnCalculate(args here)
{
    ArrayResize(candles, Bars);

    for(int i = MathMax(Bars-2-IndicatorCounted(), 1); i >= 0; i--)
    {            
        candles[i] = new Candlestick();

        // Do stuff with this candle (and other candles) here e.g.
        if(candles[i+1].type == BULLISH) Print("Last candle was Bullish");
    }
}

When I do this I get memory leak errors. It seems that I need to delete the pointers to the candles in that dynamic array. The problem is, when and where? Because I need them in the next iteration of the for(){...} loop. So I can't delete it there.

When I delete it in the OnDeinit() function there are still candles out there and I still get the leak error.

How come?


Solution

  • You might have already realised, the MQL4 code is not C.

    Among many important differences, the key here is what does the code-execution platform ( the MetaTrader Terminal 4 ) do in what moment.

    OnCalculate() is a zombie-alike process, which gets invoked many times, but anyway, definitely not under your control.

    Next, OnCalculate() by-design does not mean a new Bar.


    How to?

    MQL4 conceptually originates from days, when computing resources were many orders smaller and much more expensive in terms of their time-sharing CPU-MUX-ing during a code execution phase.

    Thus the MQL4-user-domain language retains benefits from some hidden gems, that are not accessible directly. One of these is a very efficient register-based update-processing and keeping dynamic resources allocations on minimum, for their devastatingly adverse effects on Real-Time execution predictability.

    This will help you understand how to design & handle your conceptual objects way smarter, best by mimicking this "stone-age"-but-VERY-efficient behaviour ( both time-wise & memory-wise ), instead of flooding your memory-pool with infinite amount of unmanaged instances upon each call of OnCalulate() which sprinkles an endless count of new Candlestick(); // *--> candles[]


    A best next step:

    If in doubt, just read about best practices for ArrayResize() in the platform localhost-help/documentation, to start to realise the things that introduce overheads ( if not blocks ) in a domain, where nanoseconds count & hurt in professional software design.