New MetaTrader 4 Platform build 1045 - page 3

 
JC:
Yes, it's valid, like it is valid in C++, but it's horrible. Given a pointer to Class2, what the dynamic_cast in effect produces is a pointer to a new, uninitialised instance of Class1. It is hard to describe this as a "cast".

I'd be amazed if that is the case. Casting in all of it's forms should never create a new object.

A dynamic cast should just check the type hierarchy and if compatible return the same "pointer" of the input object. In multiple inheritance languages this "pointer" can be different, but in MQL4 it will be the same.

If the type cast is incompatible MQL4 will return NULL from the dynamic_cast

Typecasting - Data Types - Language Basics - MQL4 Reference
Typecasting - Data Types - Language Basics - MQL4 Reference
  • docs.mql4.com
Typecasting - Data Types - Language Basics - MQL4 Reference
 
James Cater:

If the type cast is incompatible MQL4 will return NULL from the dynamic_cast

(This topic about the release of build 1045 isn't really the place for what this discussion is turning into, but nevertheless...)

It depends what "compatible" is deemed to mean. Take the following simpler example, where a Class2* is turned into a Class1*, creating a sort of static instance of Class1 where the constructor doesn't get called. This is all fairly similar to C++; it's just horrible.

#property strict

class Class1 {
public:
   Class1() {Print("Class1 constructor");}
   void Test() {Print("Class1");}
};

class Class2 {
};

void OnStart()
{
   Class2 * x2 = new Class2();
   Class1 * x1 = dynamic_cast<Class1*>(x2);
   x1.Test();
   delete x1;
   delete x2;
}
 

I think you are mistaken. I have tracked down the real behaviour here and the only reason the code does not crash is because your TestMe() method does not modify the object, therefore the compiler is resolving it as a static "C" like call that doesn't actually need a this pointer.

I've expanded the original test case to show you the difference. In all cases the dynamic_cast from Class2* to Class1* will always return NULL.

#property strict

class Class1 {
   int foo;
public:
   Class1() : foo(0) { Print("Class1 ctor"); }
   void TestMe1() { Print("TestMe1");}
   void TestMe2() { foo++; Print("TestMe2");}
};

class Class2 {
};

void OnStart()
{
   Class1 * x1 = new Class1();
   Class2 * x2 = new Class2();

   Test(x1);
   Print("OnStart 1");
   Test(x2); // Note the dynamic cast from Class2 to Class1 which is permitted here, inside Test()...
  
   delete x1;
   delete x2;
}

void Test(void * pClass)
{
   Class1 * pObj = dynamic_cast<Class1*>(pClass);
   Print("Test - pObj == NULL ", pObj == NULL);
  
   pObj.TestMe1(); // No-op method that does not need a this pointer at all
   pObj.TestMe2(); // This will crash with a NULL pointer
}
 
James Cater:

I think you are mistaken. [...]

I think we are basically in agreement.

What we are both saying is that you can cast any pointer A to pointer B if the member functions which are then used in B are, in effect, static.

If you want a really fun example, halfway between your example and mine, then try the following. This says that the dynamic cast fails, but the subsequent use of x1.Test() nevertheless succeeds. (It doesn't work if the methods used in Class1 try to access member variables such as mVal; it only works if the call is, in effect, static.)

#property strict

class Class1 {
public:
   int mVal;
   void Test() {Print("Class1 Test()");}
};

class Class2 {
public:
   int mVal;
   void Test() {Print("Class2 Test()");}
};

void OnStart()
{
   Class2 * x2 = new Class2();
   Class1 * x1 = dynamic_cast<Class1*>(x2);
   if (x1 == NULL) Print("Cast failed...");
   x1.Test();
   delete x1;
   delete x2;
}
 
JC:

I think we are basically in agreement.


Lol, you did probably more work than the testers in MQ.

After all, the dynamic cast is rarely a part of the logic, as the developer usually knows exactly what sort of class he expects. But it was interesting to follow you.

 

I have a problem with my EA in the latest build - 1045. When switching TFs or Symbols EA is not initialized. Example:

1. I have EA running on M1

2. I switch to M5

3. I get "uninit reason 3", EA is removed from the chart but TF is not changed, it remains on M1

4. I press M5 again and this time TF is changed and EA is initialized properly

The same happens when changing Symbol (dragging other symbol on the chart).

With this EA problem happens every time. I have other EAs and this problem occurs more or less frequently.

I believe it's a bug in the new build 1045.

 
Marcin Madrzak:

I have a problem with my EA in the latest build. When switching TFs or Symbols EA is not initialized. Example:
1. I have EA running on M1
2. I switch to M5
3. I get "uninit reason 3", EA is removed from the chart but TF is not changed, it remains on M1
4. I press M5 again and this time TF is changed and EA is initialized properly
The same happens when changing Symbol (dragging other symbol on the chart).
With this EA problem happens every time. I have other EAs and this problem occurs more or less frequently.
I believe it's a bug in the new build. 

Same here!
I have 2 MT4 platforms, one of them have problem which one you have. 2nd of them works perfect.

I will start to find solution for it, next week. I hope I will get good answers for it here.

 

In my EA's I have the divide by 0 problem fixed, but they still dissapear from charts.

And, I can't find any pattern.

They started to dissapear since the previous update.

Usually on MT4 startup, but also randomly during normal usage.

I use only one EA applied to several instruments, and they don't get removed from all the charts, just randomly.

It's not a good situation. 

 
Marcin Madrzak: I believe it's a bug in the new build. 
What build? There are no mind readers here.
 
whroeder1:
What build? There are no mind readers here.

We are in the thread about build 1045 thus I did not include the number :) And yes, it occurs on 1045.

P.S. Updated original post for clarification. 

Reason: