Strange problem with recursive function

 


Last week I was programming a (recursive) function and I ran into some strange 'variable accessing/allocating' behaviour. Let me explain:

The recursive function has one input parameter: an array by reference. So, afaik only the pointer is passed to the function. The function itself has one array declared locally. I assume the MQL compiler works similar to other programming languages and will put this testarrayB on the stack. Ok, let's show the MQLcode in order to explain the weirdness:

int testcount=1;
void test2(int& testarray[])
{
   int testarrayB[1];
   if(testcount>=3) return(0);
   testarrayB[0]=-testcount;

   Print(testcount+" @ entry testarray[0] ="+testarray[0]);
   Print(testcount+" @ entry testarrayB[0]="+testarrayB[0]);
   
   testcount=testcount+1;
   test2(testarrayB);
   
   Print(testcount+" @ exit testarray[0] ="+testarray[0]);
   Print(testcount+" @ exit testarrayB[0]="+testarrayB[0]);
}

int start()
{
   int intarray[1];
   intarray[0]=0;
   test2(intarray);
   return(0);
}

When this script is run, the test2() function is invoked from the start(). The testarray[] array in test2() will directly point to the intarray[] array declared in the start() function. testarrayB[] is allocated on the stack of test2() and assigned the value -testcount, this is the value -1. Ok, so far nothing is wrong. But, the test2 function will invoke itself and will pass the location of the testarrayB[] array to itself, ie. recurse to itself. I assume again, a new testarrayB[] is declared on the stack and the testarray[] will directly point to the previous testarrayB[] on the stack. But, let's look at the script's output generated by the print statements:

loaded successfully
1 @ entry testarray[0] =0
1 @ entry testarrayB[0]=-1
2 @ entry testarray[0] =-2
2 @ entry testarrayB[0]=-2
3 @ exit testarray[0] =-2
3 @ exit testarrayB[0]=-2
3 @ exit testarray[0] =0
3 @ exit testarrayB[0]=-2


The first two lines starting with 1 are OK. testcount is the digit on the left, and the arrays have the correct values, 0 and -1. The 3rd and 4th lines starting with 2 are _NOT_ OK, both have a value of -2. The second time the function is invoked, the testarray[] should point to the array testarrayB[] which was declared the first time the function was called. So, the value which should be in the testarray[0] should be -1 and _NOT_ -2.

After testing a while my only conclusion is both intarrayB[] and testarray[] point to the same location in memory?

This couldnt possibly be right??

Can anyone explain this behaviour?

Thanks!
Alexander

 

This looks indeed strange.

Does it only happen with arrays?

 
alexander_1974:

I assume the MQL compiler works similar to other programming languages and will put this testarrayB on the stack. Ok, let's show the MQLcode in order to explain the weirdness:

I would have made the same assumption as you, but we're wrong. The small print of the MQ4 documentation says that arrays are always static. From https://book.mql4.com/variables/arrays:

All arrays are static, i.e. are of static type even if at the initialization this is not explicitly indicated. It means all arrays preserve their values between calls of the function, in which the array is declared (see Types of Variables)

As a result, the following code prints 12345678 on both calls to the subroutine, whereas in most languages you'd expect it to print 12345678 and then zero:

void start()
{
   subroutine();
   subroutine();
}

void subroutine()
{
   int testarray[1];
   
   // On the first call *only*, set the value of testarray[0]
   static int lCallsToSubroutine = 0;
   if (lCallsToSubroutine == 0) {
      testarray[0] = 12345678;
   }
   lCallsToSubroutine++;
   
   Print("Value of testarray[0] on call " , lCallsToSubroutine , " is " , testarray[0]);
}
 
jjc:

I would have made the same assumption as you, but we're wrong. The small print of the MQ4 documentation says that arrays are always static. From https://book.mql4.com/variables/arrays:

As a result, the following code prints 12345678 on both calls to the subroutine, whereas in most languages you'd expect it to print 12345678 and then zero:



OK, thanks. That explains this behaviour.

Then the only question remains, why would they do implement it this way? The only reasonable explanation I can think of are passing indicatorbuffer arrays to a function, as the compiler doesnt know how much space it has to allocate on the stack - it varies.

But, OK nevertheless, thanks for your quick response!

Alexander