Stack overflow in 'C:\Program Files\MetaTrader 4\MQL4\Experts\FxCashEarner Vs.1.0.ex4' - page 2

 
if (Cursor >= 0)
{
        Rows = MySqlCursorRows(Cursor);
        Print (Rows, " row(s) selected.");
        for (i=0; i<Rows; i++) {

                if (MySqlCursorFetchRow(Cursor)) {
                        vUsername = MySqlGetFieldAsString(Cursor, 1);     //
                        vPassword = MySqlGetFieldAsString(Cursor, 2);     //
                        vFxacctno = MySqlGetFieldAsInt(Cursor, 3);     //
                        vAccesscode = MySqlGetFieldAsInt(Cursor, 7);      //
                        vExpirydate = MySqlGetFieldAsDatetime(Cursor, 8); //
                        vSubcode = MySqlGetFieldAsInt(Cursor, 9);        //

                        if(MyUsername!=vUsername) {
                            ...
                        }

                        if(MyPassword!=vPassword) {
                            ...
                        }

                        if(AccessCode!=vAccesscode) {
                            ...
                        }

                        if(MySubIdCode!=vSubcode) {
                            ...
                        }

                        MyExpiryDate = vExpirydate;
                        if(TimeCurrent()>MyExpiryDate) {
                            ...
                            return(0);
                        }

                        if(AccountNumber()!=vFxacctno) {
                            ...
                            return(0);
                        }
                        MySqlCursorClose(Cursor); // NEVER FORGET TO CLOSE CURSOR !!!
                }   else   {
                        Print ("Cursor opening failed. Error: ", MySqlErrorDescription);
                }
        }
        MySqlCursorClose(Cursor); // NEVER FORGET TO CLOSE CURSOR !!!
        MySqlDisconnect(DB);
        Print ("Disconnected. Script done!");
}

The red changes could solve the issue. Might be worth a try ?

And now even further... Looking at the "Cursor opening failed" error message. Then this implies, that the entire if else is malformed. It should NOT belong there at all. So the code might be more or less looking like this:

// all the opening cruft....

if (Cursor >= 0) {
        Rows = MySqlCursorRows(Cursor);
        Print (Rows, " row(s) selected.");
        for (i=0; i<Rows; i++) {
                if (MySqlCursorFetchRow(Cursor)) {
                        vUsername = MySqlGetFieldAsString(Cursor, 1);     //
                        vPassword = MySqlGetFieldAsString(Cursor, 2);     //
                        vFxacctno = MySqlGetFieldAsInt(Cursor, 3);     //
                        vAccesscode = MySqlGetFieldAsInt(Cursor, 7);      //
                        vExpirydate = MySqlGetFieldAsDatetime(Cursor, 8); //
                        vSubcode = MySqlGetFieldAsInt(Cursor, 9);        //

                        if(MyUsername!=vUsername) {
                                ...
                        }

                        if(MyPassword!=vPassword) {
                                ...
                        }

                        if(AccessCode!=vAccesscode) {
                                ...
                        }

                        if(MySubIdCode!=vSubcode) {
                                ...
                        }

                        MyExpiryDate = vExpirydate;
                        if(TimeCurrent()>MyExpiryDate) {
                                ...
                                        return(0);
                        }

                        if(AccountNumber()!=vFxacctno) {
                                ...
                                        return(0);
                        }
                }
        }

        MySqlCursorClose(Cursor); // NEVER FORGET TO CLOSE CURSOR !!!
} else {
        Print ("Cursor opening failed. Error: ", MySqlErrorDescription);
}

MySqlDisconnect(DB);
Print ("Disconnected. Script done!");
 
Opengates:

@Demos: Tried everything you suggested but the result still remained the same - Stack Overflow!

Hello again,

a) I checked again and I can see that in the beginning you are declaring string ReadIni; but after you are using ReadIni as a function

string ReadIni;
 // reading database credentials from INI file
 Host = "ReadIni(INI, MYSQL, pHost)";
 User = "ReadIni(INI, MYSQL, pUser)";

b) I realised that on each if (MySqlCursorFetchRow(Cursor)), you are keep assigning vUsername and more

for (i=0; i<Rows; i++)
     
         if (MySqlCursorFetchRow(Cursor)) {
             vUsername = MySqlGetFieldAsString(Cursor, 1);     //
             vPassword = MySqlGetFieldAsString(Cursor, 2);     //
             vFxacctno = MySqlGetFieldAsInt(Cursor, 3);     //
             vAccesscode = MySqlGetFieldAsInt(Cursor, 7);      //
             vExpirydate = MySqlGetFieldAsDatetime(Cursor, 8); //
             vSubcode = MySqlGetFieldAsInt(Cursor, 9);        //

 but the value of vUsername,vPassword should be the same each time; so no reason to keep assigning

 

Regarding all those remarks, they are not related to Stack Overflow message; my assumption about that matter is that some of your functions ReadIni(), MySqlCursorOpen and more, may contain an infinite loop, and as such, you are getting error message above. As such, you may have to post some more code  

 

best regards 

 
Demos:

All those remarks are intended for purposes other than the Stack Overflow message; my assumption regarding that matter is that some of your functions ReadIni(), MySqlCursorOpen and more, may contain an infinite loop, and as such, you are getting error message above. As such, you may have to post some more code

Follow his curly brackets from the inside if clauses to the outside and you see that they are malformed. Somehow an ending curly bracket has slipped and thus re-aligned all his code to a different if/else/for branch that causes the issue. In this particular case the if test for "is cursor open" has been re-assigned to the inner if clause inside the for loop. This causes:

a) ... wrong generated code

b) ... not doing what is intended

c) ... completely falsely deals with clode cursors (and thus triggers the stack overflow)

 
aakcaagac:

Follow his curly brackets from the inside if clauses to the outside and you see that they are malformed. Somehow an ending curly bracket has slipped and thus re-aligned all his code to a different if/else/for branch that causes the issue. In this particular case the if test for "is cursor open" has been re-assigned to the inner if clause inside the for loop. This causes:

a) ... wrong generated code

b) ... not doing what is intended

c) ... completely falsely deals with clode cursors (and thus triggers the stack overflow)

hello,

i saw his formatting as being for if{} else{} and not for {if{}, else{} }, but it may work on both ways :) So the problem may be inside one of the functions he (she) uses, because when we are trying to assign a function which contains an infinite loop to a variable, we get the exception error message

Update: I was able to reproduce the error; if you compile and run the following code, you will get below error message in the MQL4/Logs folder

0 20:19:43.413 practice GBPUSD,H1: initialized

1 20:19:48.412 Stack overflow in 'C:\Users\** **\AppData\Roaming\MetaQuotes\Terminal\** **\MQL4\Experts\practice.ex4' 

 

int func()
{
    return func();
}

void OnTimer()
{
    int a=func();
}

void OnDeinit(const int reason)
{    
     Print(GetLastError() ); EventKillTimer();   
}  

 

edit:  i added some more to the SRC above; it is necessary to put GetLastError() inside OnDeinit(), as first command

 
int func()
{
    return func();
}

void OnTimer()
{
    int a=func();
}

Yes this is an endless recursive calling and thus fills up the stack with return values, dataregisters and addressregisters. This is a bug in MetaTrader and should be fixed.

But! His code is still wrong and my explaination with the curly brackets still hold. Let me show again. I will paste his entire code line by line.

string ReadIni;
 // reading database credentials from INI file
 Host = "ReadIni(INI, MYSQL, pHost)";
 User = "ReadIni(INI, MYSQL, pUser)";
 Password = "ReadIni(INI, MYSQL, pPassword)";
 Database = "ReadIni(INI, MYSQL, pDatabase)";
 Port     = StrToInteger("ReadIni(INI, MYSQL, pPort)");
 Socket   = "ReadIni(INI, MYSQL, pSocket)";
 ClientFlag = StrToInteger("ReadIni(INI, MYSQL, pClientFlag)");  

 Print ("Host: ",Host, ", User: ", User, ", Database: ",Database);
 
 // open database connection
 Print ("Connecting...");
 
 DB = MySqlConnect(Host, User, Password, Database, Port, Socket, ClientFlag);
 
 if (DB == -1) { Print ("Connection failed! Error: "+MySqlErrorDescription); return(0); } else { Print ("Connected! DBID#",DB);}
 
 // executing SELECT statement
 int      vSubcode,vFxacctno,vAccesscode,i,Cursor,Rows;
 string   vUsername,vPassword,FXOpen,Query;
 datetime vExpirydate,MyExpiryDate;
  
 Query = "SELECT username, password, accesscode, expirydate, subcode, fxacctno FROM table";
 Print ("SQL> ", Query);
 Cursor = MySqlCursorOpen(DB, Query);
 
 if (Cursor >= 0)          // part B
    {
     Rows = MySqlCursorRows(Cursor);
     Print (Rows, " row(s) selected.");
     for (i=0; i<Rows; i++)
     
         if (MySqlCursorFetchRow(Cursor)) {
             vUsername = MySqlGetFieldAsString(Cursor, 1);     //
             vPassword = MySqlGetFieldAsString(Cursor, 2);     //
    A        vFxacctno = MySqlGetFieldAsInt(Cursor, 3);     //
             vAccesscode = MySqlGetFieldAsInt(Cursor, 7);      //
             vExpirydate = MySqlGetFieldAsDatetime(Cursor, 8); //
             vSubcode = MySqlGetFieldAsInt(Cursor, 9);        //
           
            if(MyUsername!=vUsername) {
    6       Print("This username is not existing in our database!"); return(0); 
            }
            
            if(MyPassword!=vPassword) {
    5       Print("Incorrect password! Try again."); return(0);
            }
            
            if(AccessCode!=vAccesscode) {
    4       Print("Access Code entered is either incorrect, expired or you are not authorized to use this software!"); return(0);
            }
            
            if(MySubIdCode!=vSubcode) {
    3       Print("Enter correct subscription identification code!"); return(0);
            }
            
            MyExpiryDate = vExpirydate;
            if(TimeCurrent()>MyExpiryDate) {
    2       Print("Your access code has expired and as a result, your access period is over" +
                  TimeToStr(MyExpiryDate,TIME_DATE|TIME_SECONDS),"Renew your subscription today @ www.fxdominion.com/245dea");
            return(0);  } 
            
            if(AccountNumber()!=vFxacctno) {
            Comment("Unauthorized User! Get for your own copy @ www.mysite.com today!",GetLastError());
    1       Print("Unauthorized User! Get for your own copy @ www.mysite.com today!",GetLastError());
            return(0); 
            }
            
     MySqlCursorClose(Cursor); // NEVER FORGET TO CLOSE CURSOR !!!
 A  }  else   {
     Print ("Cursor opening failed. Error: ", MySqlErrorDescription);
    }  
 MySqlDisconnect(DB);
 Print ("Disconnected. Script done!");
}

You can see that the MySqlCursorClose anchors to his inner if (The part maked with A).

Curly brackets for the part 1 (AccountNumber) is opened and closed correctly.

Curly brackets for the part 2 (TimeCurrent) is opened and closed correctly.

Curly brackets for the part 3 (MySubIdCode) is opened and closed correctly.

Curly brackets for the part 4 (AccessCode) is opened and closed correctly.

Curly brackets for the part 5 (MyUserName) is opened and closed correctly.

Curly brackets for the part A (MySqlCursorFetchRos) is logically (for the compiler) opened and closed correctly.

And here is the problem (at part A). The eye is fooled here. The gray part above (the first A at the top) doesn't fit the logical code at the bottom part (also market with A).

The first if at the far top deals with (Cursor >= 0) and if Cursor is greater or equal to 0) then it should dive into the if statement. If (Cursor = -1) for example (because Cursor failed to open) then it should dive into the } else { and print cursor openeing failed and later on disconnect MySqlDisconnect.

But somehow a curly bracket has slipped in his code (and he applied the missing one to the bottom (thus removing the compiler error) but the curly brackets are not balanced correctly.

The second code part on page two at the top first comment solves it. It doesn't make sense to close the cursor within a for loop repeadly. The else of part A at the bottom belongs to part B at the top.

 

Second part!

Now let's eleminate (for us to understand) all the inner if statement (part 1 to 6)

string ReadIni;
 // reading database credentials from INI file
 Host = "ReadIni(INI, MYSQL, pHost)";
 User = "ReadIni(INI, MYSQL, pUser)";
 Password = "ReadIni(INI, MYSQL, pPassword)";
 Database = "ReadIni(INI, MYSQL, pDatabase)";
 Port     = StrToInteger("ReadIni(INI, MYSQL, pPort)");
 Socket   = "ReadIni(INI, MYSQL, pSocket)";
 ClientFlag = StrToInteger("ReadIni(INI, MYSQL, pClientFlag)");  

 Print ("Host: ",Host, ", User: ", User, ", Database: ",Database);
 
 // open database connection
 Print ("Connecting...");
 
 DB = MySqlConnect(Host, User, Password, Database, Port, Socket, ClientFlag);
 
 if (DB == -1) { Print ("Connection failed! Error: "+MySqlErrorDescription); return(0); } else { Print ("Connected! DBID#",DB);}
 
 // executing SELECT statement
 int      vSubcode,vFxacctno,vAccesscode,i,Cursor,Rows;
 string   vUsername,vPassword,FXOpen,Query;
 datetime vExpirydate,MyExpiryDate;
  
 Query = "SELECT username, password, accesscode, expirydate, subcode, fxacctno FROM table";
 Print ("SQL> ", Query);
 Cursor = MySqlCursorOpen(DB, Query);
 
 if (Cursor >= 0)
    {
     Rows = MySqlCursorRows(Cursor);
     Print (Rows, " row(s) selected.");
     for (i=0; i<Rows; i++)
     
         if (MySqlCursorFetchRow(Cursor)) {
             vUsername = MySqlGetFieldAsString(Cursor, 1);     //
             vPassword = MySqlGetFieldAsString(Cursor, 2);     //
             vFxacctno = MySqlGetFieldAsInt(Cursor, 3);     //
             vAccesscode = MySqlGetFieldAsInt(Cursor, 7);      //
             vExpirydate = MySqlGetFieldAsDatetime(Cursor, 8); //
             vSubcode = MySqlGetFieldAsInt(Cursor, 9);        //

     // if statements removed           
            
     MySqlCursorClose(Cursor); // NEVER FORGET TO CLOSE CURSOR !!!
    }  else   {
     Print ("Cursor opening failed. Error: ", MySqlErrorDescription);
    }  
 MySqlDisconnect(DB);
 Print ("Disconnected. Script done!");
} 

Now you see the missbalanced curly brackets clearer. While the eye sees the MySqlCursorClose correctly placed. The logic otoh is wrong. One may assume that the } else { statement belongs to the first if (cursor >= 0) but it's not. From the logic here the } else { part belongs to the inner if (MySqlCursorFetchRow).

So what happens is this. Say we get 300 Rows returned. the for loop runs 300 iterations. Testing 300 times (MySqlCursorFetchRow) and does it's jump inside there whenever necessary. Calling MySqlCursorClose afterwards.

For example let's say within 300 iterations it jumps 50 times into the if clause. Then it executes 50 times the MySqlCursorClose. Maybe it also calls MySqlDisconnect. From the Print (Cursor opening failed) message, it makes more sense to attach that } else { part to the first if (cursors >= 0) because we initially opened the database, we opened the cursors... and if the open fails we print the "cursor opening failed" message and disconnect mysql...

And even if we look at it differently. If we remove the last curly bracket } at the bottom and place it above MySqlCursorClose then it's all correct again as it should.

For example: OpenDB... OpenCursor... Cursor >= 0... get row.... for loop... inner if .. some other if checks... leaving inner if... loop the for loop 300 iterations (the curly brackets are missing thus it makes the inner if as one statement and therefore loops that)... and after 300 iterations are done it closes the Curors and disconnects SQL.

 

* I updated my previous post because i included some more code for being able to see the error in the log file 

 

aakcaagac:

Yes this is an endless recursive calling and thus fills up the stack with return values, dataregisters and addressregisters. This is a bug in MetaTrader and should be fixed.

 Hmm, I am not sure it is a bug but maybe the way CPUs work; of course it may be an issue with the assembly code (who knows hehe) or a plain logical error FWIW, a c file compiled in GCC crashes on Windows as well

 

aakcaagac:

 

And here is the problem (at part A). The eye is fooled here. The gray part above (the first A at the top) doesn't fit the logical code at the bottom part (also market with A).

The first if at the far top deals with (Cursor >= 0) and if Cursor is greater or equal to 0) then it should dive into the if statement. If (Cursor = -1) for example (because Cursor failed to open) then it should dive into the } else { and print cursor openeing failed and later on disconnect MySqlDisconnect.

 The A else belongs to the A if, which belongs to for loop; you can check the following code 

    for (a=0; a<8; a++)
    
    if (b<5)
    {
        Alert("if"); b++;
    }
        
    else 
    {
        Alert("else"); b++; 
    }   

 So, once we get past if (Cursor >= 0), the for loop takes command (along with if and else). On my part, i also noticed that "MySqlCursorClose(Cursor)" which is right above else, looks as it may close Cursor in a way that "if (MySqlCursorFetchRow(Cursor))" (in A) becomes false, so we are going to "else" right afterthe first run of the for loop 

 

best regards 

 
aakcaagac:

Second part!

Now you see the missbalanced curly brackets clearer. While the eye sees the MySqlCursorClose correctly placed. The logic otoh is wrong. One may assume that the } else { statement belongs to the first if (cursor >= 0) but it's not. From the logic here the } else { part belongs to the inner if (MySqlCursorFetchRow).

oh well, I did not understand before; we are saying the same words, so you may disregard my last post :) 
 
Demos:

The A else belongs to the A if, which belongs to for loop;

Exactly! But this is wrong. The A else should belong to the B if because of the MySqlCursorClose command.

Ok to say the truth, I don't know how the MySqlCursorClose work but to my understanding let's pretend it to work like a file open and file close.

int var = FileOpen();

if (var != 0) {
  int row = ReadRows();

  for (i = 0: row > i; i++)
    if (mysql_inner_if) {
    ...
    }

   FileClose();
)

But in his logic.

int var = FileOpen();

if (var != 0) {
  int row = ReadRows();

  for (i = 0: row > i; i++)
    if (mysql_inner_if) {
      ...

      FileClose();
    }
)

So in his logic he placed the FileClose (or MySqlCursorClose) within the inner if. Nonetheless the for loop continues running it can go inside the inner if and closes the FileClose multiple times. Even if the FileClose has been closed previously. Thus even with a closed handle he still tries reading data from the database. Even that, the database is also disconnected while the for loop continues iterating.

Personally I wouldn't code like that. I would first start ordering and aligning the curly brackets correctly, to avoid confusion and irritations. 

 
Demos:
oh well, I did not understand before; we are saying the same words, so you may disregard my last post :) 
No problem. The more eyes, the better we figure the issues.
Reason: