Let's discuss how to avoid memory leak in a C like language and possibly make this thread informative

 

Question I - dangling pointer, memory leak in MQL4, is it same as C/C++, in terms of definition and their actual behaviors?

Question II - citing William's words [ https://www.mql5.com/en/forum/347811 ], does avoid using `new()` will get rid of most if not all memory leaks? From my perspective n his words, it seems like when `new()` wasn't called then the unused reference and its content would be magically garbage collected just like Java's GC.

Question III - do we really need the custom destructor or any explicit `delete` when the only purpose is to free up the RAM?

Question IV - is there any auto RAM clearing up in place?

@@@ I - IV are highly related, and they all share a common goal - to keep an EA runs indefinitely without the need to restart @@@

Question IV - I suspect sometimes an implicit copy constructor will work under the scene but a function with explicit return type T will always require an explicit copy constructor even though T's data members only contain primitive values that could be easily copied, so why? (I personally feel that it should stick to either one)

```
//Question IV code sample//
T doSomething(T *element){
  return T;//requires copy constructor to return, if copied == a new object is created
}

void doDoDo(T *element){
  T newElement = element;//here, the values are copied to a new object of T type without the need of explicit copy constructor
}
```

I'm new to MQL4/5 and recently trying to transit my half-way-trained-broken knowledge and skills into here, if you are also wondering these questions, we could check and progress together. And if you spot any misconception above, please spit them all at my face, much thanks.

Leaked memory
Leaked memory
  • 2020.07.28
  • Jan Tarnogrocki
  • www.mql5.com
Hello, when running the code below MT4 prints: 2020.07.28 11:42:00.097 Class EURUSD,M1: 16 bytes of leaked memory 2020.07.28 11:42:00...
 

Ting:

Question III - do we really need the custom destructor or any explicit `delete` when the only purpose is to free up the RAM?

Question IV - is there any auto RAM clearing up in place?

  1. Yes, you do. If you new a handle, it is up to you to delete it later.
  2. No, there is not.
  3. Generally avoid them.
 

MQL has nothing to do with C in term of memory.

MQL is a managed language, the coder can't create real memory leak. If you forget to "delete" a pointer, the platform will inform you about it.

There is no effective reason to not use pointers in MQL. They are not real pointers anyway.

See this topic : https://www.mql5.com/en/forum/450676/page3#comment_48103170

Declaring Template Class Variables - How to avoid pointer-less code?
Declaring Template Class Variables - How to avoid pointer-less code?
  • 2023.07.13
  • Alain Verleyen
  • www.mql5.com
Just because you don't want to use a pointer. I don't hate memory-saving and polymorphism (haha), it is just that i don't think variable declaration i comes under these. Often when this happens the program ends without the ondeinit() being able to run
 
Alain Verleyen #:

MQL has nothing to do with C in term of memory.

MQL is a managed language, the coder can't create real memory leak. If you forget to "delete" a pointer, the platform will inform you about it.

There is no effective reason to not use pointers in MQL. They are not real pointers anyway.

See this topic : https://www.mql5.com/en/forum/450676/page3#comment_48103170

Thanks for the link, it reveals the existence of  "assignment constructor" to me and complete the Question V (mistakenly claim "Question IV" twice in question, it should be V). Or kindly have someone corrects it before the thread goes too long.


Now I find some interesting behaviors of MQL "pointer", "address" and still examining them:

- other than a class type / object, a variable can't have a pointer, not even struct can have a pointer (only object is addressable)

- when prints out the latest object address, it is actually the total active objects at that execution time (so if this number keeps going up in program, may means memory leaks)


   for(int i=0; i<5; i++){
      OHLC looBar = OHLC(1.0001,1.0333,1.0000,1.0222);//local automatic variable?
      Print(&looBar);//same number, let say, 9
   }//9th object removed, total active objects now would be 8

OHLC anoBar = OHLC(1.0001,1.0333,1.0000,1.0222);

Print(&anoBar);//9 again


Provided that looBar is not static variable, it should no longer exist here, the memory that this block was holding should now be free and returned to the memory pool.

I wonder does the looBar really keeps getting initialized and de-initialized and finally its memory is de-allocated n returned to the pool?
 
Ting #:

Thanks for the link, it reveals the existence of  "assignment constructor" to me and complete the Question V (mistakenly claim "Question IV" twice in question, it should be V). Or kindly have someone corrects it before the thread goes too long.


Now I find some interesting behaviors of MQL "pointer", "address" and still examining them:

- other than a class type / object, a variable can't have a pointer, not even struct can have a pointer (only object is addressable)

- when prints out the latest object address, it is actually the total active objects at that execution time (so if this number keeps going up in program, may means memory leaks)


   for(int i=0; i<5; i++){
      OHLC looBar = OHLC(1.0001,1.0333,1.0000,1.0222);//local automatic variable?
      Print(&looBar);//same number, let say, 9
   }//9th object removed, total active objects now would be 8

OHLC anoBar = OHLC(1.0001,1.0333,1.0000,1.0222);

Print(&anoBar);//9 again


Provided that looBar is not static variable, it should no longer exist here, the memory that this block was holding should now be free and returned to the memory pool.

I wonder does the looBar really keeps getting initialized and de-initialized and finally its memory is de-allocated n returned to the pool?

use the code button </>  or Alt+S to post code.

 provide code that compiles and you are more likely to get answers.

 
Ting #:
   for(int i=0; i<5; i++){
      OHLC looBar = OHLC(1.0001,1.0333,1.0000,1.0222);//local automatic variable?
      Print(&looBar);//same number, let say, 9
   }//9th object removed, total active objects now would be 8

See my code and compilation errors:

class OHLC
  {
   const double open;
   const double high;
   const double low;
   const double close;
public:
          OHLC(double a_open, double a_high, double a_low, double a_close)
            : open(a_open),
              high(a_high),
              low(a_low),
              close(a_close) {}
  };

void OnStart()
  {
   OHLC looBar = OHLC(1.0001,1.0333,1.0000,1.0222);
  }

I made the fields constant, which resulted in the implicit removal of the = operator.

That is, the following line creates 2 instances, not 1 (in your code):

OHLC looBar = OHLC(1.0001,1.0333,1.0000,1.0222);
 
Vladislav Boyko #:
That is, the following line creates 2 instances, not 1 (in your code):

This is how we can make sure of it:

class OHLC
  {
   double open;
   double high;
   double low;
   double close;
public:
          OHLC(double a_open, double a_high, double a_low, double a_close)
            : open(a_open),
              high(a_high),
              low(a_low),
              close(a_close) { Print(__FUNCSIG__); }
          OHLC() { Print(__FUNCSIG__); }
  };

void OnStart()
  {
   OHLC looBar = OHLC(1.0001,1.0333,1.0000,1.0222);
  }

(I added a default constructor and made the fields non-constant so that the code would compile)

 
Vladislav Boyko #:
That is, the following line creates 2 instances, not 1 (in your code):

A more visual example that demonstrates that you first create 2 instances and then copy the fields from one to the other using an implicitly overloaded assignment operator (in this example I overloaded it explicitly):

class OHLC
  {
   double open;
   double high;
   double low;
   double close;
public:
          OHLC(double a_open, double a_high, double a_low, double a_close)
            : open(a_open),
              high(a_high),
              low(a_low),
              close(a_close) { Print(__FUNCSIG__); }
          OHLC() { Print(__FUNCSIG__); }
   void   operator=(const OHLC&) { Print(__FUNCSIG__); }
  };

void OnStart()
  {
   Print("start");
   OHLC looBar = OHLC(1.0001,1.0333,1.0000,1.0222);
   Print("end");
  }


 
Ting #:
for(int i=0; i<5; i++){
      OHLC looBar = OHLC(1.0001,1.0333,1.0000,1.0222);//local automatic variable?

The correct way to create an object with an automatic pointer at each iteration:

class OHLC
  {
   double open;
   double high;
   double low;
   double close;
public:
          OHLC(double a_open, double a_high, double a_low, double a_close)
            : open(a_open),
              high(a_high),
              low(a_low),
              close(a_close) { Print(__FUNCSIG__); }
          OHLC() { Print(__FUNCSIG__); }
  };

void OnStart()
  {
   for(int i=0; i<5; i++)
     {
      OHLC looBar(1.0001,1.0333,1.0000,1.0222);
     }
  }
 
Ting:

It will be easier for you to understand if you read at least this:

Creating and Deleting Objects

Object Pointers

Object-Oriented Programming (all subsections)

 
This attempts to create an anonymous object, then copy construct looBar, and finally deconstruct the anonymous object.
  OHLC looBar = OHLC(1.0001,1.0333,1.0000,1.0222);//local automatic variable?
Simplify your code.
  OHLC looBar(1.0001,1.0333,1.0000,1.0222);
Reason: