Critical bug: MT5 seems to corrupt dynamic memory upon SymbolPeriod switch. Code attached.

 
MT5 version 5.00 build 5062 on 3 Jun 2025
Code to reproduce attached.

I have discovered that MT5 overwrites any dynamically-created object's member that contains the name of the <current chart symbol> with a <new chart symbol> when ChartSetSymbolPeriod(ChartID(), <new symbol>, _Period) is called. This can be a sign of a serious system instability in the new MT5 build.

For example:
1. I have created a random class that contains two string members: one for storing the chart symbol name, and another for storing exactly the same name but with some random string appended (in this case I use "&this" for debugging purposes).
The constructor for the object initializes both string members.
class CEATestModule{
public:
   const string m_strSymbol;
   string m_strTestModuleID;
   
   CEATestModule(string strSymbol): m_strSymbol(strSymbol){
      m_strTestModuleID = StringFormat("%s_%I64u", m_strSymbol, &this);
   };

2. I then have a global pointer to this class
CEATestModule* g_objTestModule;

which I initialize in OnInit()

g_objTestModule = new CEATestModule(_Symbol);


3. Then somewhere inside the code, a call to ChartSetSymbolPeriod() should happen to change chart symbol. I do it in OnTimer() three seconds after the launch:

void OnTimer(){
   datetime dtCurrentTime = TimeLocal();
   
   static datetime s_dtStartTime = TimeLocal();
   static bool s_bSymbolChanged = false;
   if(!s_bSymbolChanged && dtCurrentTime - s_dtStartTime >= 3){
      ChartSetSymbolPeriod(ChartID(), "AUDCAD", _Period);//Replace "AUDCAD" with any symbol in your MarketWatch
      s_bSymbolChanged = true;
   }
}

It's important NOT to delete the pointer in OnDeinit(). This is supposed to happen upon global deinitialization (omitted here). The global state, of which the object is part of, must carry into the new symbol.

4. Finally, at the very beginning of OnInit(), I verify the content of the carried object:

int OnInit(){
   if(CheckPointer(g_objTestModule) == POINTER_DYNAMIC)
      g_objTestModule.AssertConsistency();
   else   
      g_objTestModule = new CEATestModule(_Symbol);
   void AssertConsistency(){
      int iPos = StringFind(m_strTestModuleID, "_");
      string strCorrectSymbol = StringSubstr(m_strTestModuleID, 0, iPos); 
      if(m_strSymbol != strCorrectSymbol){
         DebugBreak();
         PrintFormat("Inconsistency detected: CorrectSymbol = %s; CurrentSymbol = %s", strCorrectSymbol, m_strSymbol);
      }
   }
The content of both variables should stay the same. However, the content of m_strSymbol variable that should contain the old symbol name is somehow changed, even though the content of the m_strTestModuleID variable containing the modified old symbol name stays the same.

How on Earth???

Full source code is attached.
Files:
 
kprager222:
MT5 version 5.00 build 5062 on 3 Jun 2025...

Current release is 5100 and last beta is 5106.

So please try and confirm your bug report.

 
Alain Verleyen #:

Current release is 5100 and last beta is 5106.

So please try and confirm your bug report.

I have tried on build 5100 6 Jun 2025 and confirm the bug is still there. 

The problem occurs between when OnDeinit() is finished and when OnInit() is called again. That's where MT5 appears to mess up the content of dynamically-created objects inside the EAs.
 
kprager222 #:
I have tried on build 5100 6 Jun 2025 and confirm the bug is still there. 

The problem occurs between when OnDeinit() is finished and when OnInit() is called again. That's where MT5 appears to mess up the content of dynamically-created objects inside the EAs.
I confirm and reported it to MQ attention.
 
Alain Verleyen #:
I confirm and reported it to MQ attention.
Many thanks! Will look forward to hearing from them.
Is this the right way to report bugs by the way? In this forum? In this manner? What's the right way?
 
kprager222 #:
Many thanks! Will look forward to hearing from them.
Is this the right way to report bugs by the way? In this forum? In this manner? What's the right way?
It was the right way.