Как избежать ошибки "Stack overflow" в советнике ?

 

Периодически  советник не включается в начале новых суток.

В журнале пишет такую ошибку : 2025.02.06 02:45:13.372 -Stack overflow in 'C:\Users\User\AppData\Roaming\MetaQuotes\Terminal\15039C815974EAFC08F5D72E8C042194\MQL4\Experts\Ping_pong_Limit_bs.ex4'

Cоветник выставляет сетку ордеров  BUYLIMIT & SELLLIMIT  по EURUSD.

Как избежать ошибки "Stack overflow"  в коде советника ?

Подскажите кто знает.

 

Чаще всего такая ошибка возникает из-за использования рекурсии - вызов из функции самой себя напрямую или опосредовано через вызов другой функции. Если последний вариант, то придется помучаться, чтобы найти ошибку, т. к. такая рекурсия неочевидна.

Другой вариант переполнения стека - наличие в глобальном контексте динамического массива, который неумеренно расширяется. С одной стороны, для устранения этой ошибки достаточно перенести этот массив в тело какой-нибудь функции или в класс, создающийся во время исполнения программы. Но, скорее всего, в логике расширения этого массива присутствует ошибка, т. к. он расширяется бесконечно. Лучше всего найти проблему такого бесконечного расширения.

 
Ihor Herasko #:
Другой вариант переполнения стека - наличие в глобальном контексте динамического массива, который неумеренно расширяется.

Динамический массив использует память кучи и не может переполнить стек.

fregat555:
Как избежать ошибки "Stack overflow"  в коде советника ?

Лучший вариант - обратиться к разработчику советника.

Если есть исходный код, но разработчика нет - либо заказать во фрилансе, либо опубликовать код на форуме (но не факт, что найдутся желающие тратить на это время за бесплатно).

Если нет ни исходного кода, ни связи с разработчиком, то "избежать" ошибки не получится.

 

Обычный Canvas при умелом использовании, легко вызывает такую ошибку.

У него там с деинициализация есть проблемы. 

Так что если советник рисует красивые картинки, то ковыряйте  Canvas.

 
Aleksandr Slavskii #:

Обычный Canvas при умелом использовании, легко вызывает такую ошибку.

У него там с деинициализация есть проблемы. 

Так что если советник рисует красивые картинки, то ковыряйте  Canvas.

Не замечал. Наверное, неумело использую. 
Приведите пример "умелого" использования канваса, пожалуйста. 
 
Artyom Trishkin #:
Не замечал. Наверное, неумело использую. 
Приведите пример "умелого" использования канваса, пожалуйста. 

Не сразу попал на нужную строчку, там в гифке через пару сек будет метатрейдер.

Гифка работает если нажать на неё.

Вот так можно скушать память, при "умелом использовании")))

#include <CommBag.mqh>
//+------------------------------------------------------------------+
int OnInit(void)
  {
   EventSetMillisecondTimer(10);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
void OnTimer()
  {
   MqlTick tick;
   SymbolInfoTick(_Symbol, tick);
   if(tick.ask != 0 && tick.bid != 0)
      Comm(StringFormat("ask  = %.5f\nbid  = %.5f\ntime = %s", tick.ask, tick.bid, TimeToString(tick.time, TIME_DATE | TIME_SECONDS)));
  }
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   EventKillTimer();
  }
//+------------------------------------------------------------------+


#include <Canvas\Canvas.mqh>
void Comm(string txt, color clr = clrYellow, int FontSize = 20, string Font = "Consolas", int flag = FW_BOLD)
  {
   CCanvas canvas;

   int shift = 0;
   if(ChartGetInteger(0, CHART_SHOW_ONE_CLICK))
      shift = 60;
   canvas.Erase(0x00FFFFFF);
   canvas.FontNameSet(Font);
   canvas.FontFlagsSet(flag);
   canvas.FontSizeSet(FontSize);

   int width = 0, height = 0;
   string result[];
   int size = StringSplit(txt, StringGetCharacter("\n", 0), result);
   height = (int)(FontSize * 1.8 * size);

   for(int i = 0; i < size; i++)
     {
      int w = canvas.TextWidth(result[i]);
      if(width < w)
         width = w;
     }

   canvas.CreateBitmapLabel(0, 0, "Comment", 5, 20 + shift, width, height, COLOR_FORMAT_ARGB_NORMALIZE);
   for(int i = 0; i < size; i++)
      canvas.TextOut(0, (int)(FontSize * 0.8 * i), result[i], ColorToARGB(clr, 255));

   canvas.Update(true);
  }
 
Aleksandr Slavskii #:

Не сразу попал на нужную строчку, там в гифке через пару сек будет метатрейдер.

Гифка работает если нажать на неё.

Вот так можно скушать память, при "умелом использовании")))


Только самый настоящий гений будет его так использовать.Даже случайно на столько "красиво" далеко не у всех получится 
 

Добрый вечер, день!

У меня  советник на МТ4, не 5. За основу взял известный советник хеджирования НТН. Ошибка переполнения срабатывает не постоянно, периодически.

Ниже его код:

//+------------------------------------------------------------------+
//|                                                          HTH.mq4 |
//|                                                             c0d3 |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "c0d3"
#property link      ""

extern bool trade=true;
extern string C1="EURUSD";
extern string C2="USDCHF";
extern string C3="GBPUSD";
extern string C4="AUDUSD";
extern bool show_profit=true;
extern bool enable_profit=false;
extern bool enable_loss=false;
extern bool enable_emergency_trading=true;
extern int emergency_loss=60;
extern int profit=80;
extern int loss=40;
extern int MagicNumber1=243;
extern int MagicNumber2=244;
extern int MagicNumber3=245;
extern int MagicNumber4=256;
extern int E_MagicNumber=257;
extern double lot=0.01;
//----------------------------------------------------------------------------------------------------------------------------
void verifyorder(string symbol, int MN, string direction)//function which is used to verify that the orders have been placed
{
Sleep(1000);
int ord_cnt=OrdersTotal();
for (int start=0;start<ord_cnt;start++)  
   {
      OrderSelect(start, SELECT_BY_POS, MODE_TRADES);
      if(OrderMagicNumber()==MN)
         {return;}
   }
if(direction=="LONG"){OrderSend(symbol,OP_BUY,lot,MarketInfo(symbol,MODE_ASK),3,0,0,"Hedge"+symbol,MN);}
if(direction=="SHORT"){OrderSend(symbol,OP_SELL,lot,MarketInfo(symbol,MODE_BID),3,0,0,"Hedge"+symbol,MN);}  
return;
}
//-------------------------------------------------------------------------------------------------------------
 void closeorders()
   {
      int close_ord1=OrdersTotal();
         for (int qe1=0;qe1<close_ord1;qe1++)
            {
               OrderSelect(qe1, SELECT_BY_POS, MODE_TRADES);
                 if( OrderMagicNumber()==MagicNumber1  ||
                     OrderMagicNumber()==MagicNumber2  ||
                     OrderMagicNumber()==MagicNumber3  ||
                     OrderMagicNumber()==E_MagicNumber ||
                     OrderMagicNumber()==MagicNumber4)
                     {
     if(OrderType()==OP_BUY) {RefreshRates();OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),3);Sleep(2000);}
     if(OrderType()==OP_SELL){RefreshRates();OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),3);Sleep(2000);}
                     }
            }
   closeordersverify();        
   return;        
   }
//-------------------------------------------------------------------------------------------------------------------------------- 
 void closeordersverify()
   {
      int close_ord11=OrdersTotal();
         for (int qe11=0;qe11<close_ord11;qe11++)
            {
               OrderSelect(qe11, SELECT_BY_POS, MODE_TRADES);
                 if( OrderMagicNumber()==MagicNumber1  ||
                     OrderMagicNumber()==MagicNumber2  ||
                     OrderMagicNumber()==MagicNumber3  ||
                     OrderMagicNumber()==E_MagicNumber ||
                     OrderMagicNumber()==MagicNumber4)
                     {closeorders();}
                     //if(OrderType()==OP_BUY) {OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),3);Sleep(2000);}
                     //if(OrderType()==OP_SELL){OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),3);Sleep(2000);}
            }
   return;        
   }  
//-------------------------------------------------------------------------------------  
 void doubleorders()
   {
      int ord_t=OrdersTotal();
         for (int y=0;y<ord_t;y++)
            {
            OrderSelect(y, SELECT_BY_POS, MODE_TRADES);
                              if(OrderMagicNumber()==MagicNumber1 ||
                                 OrderMagicNumber()==MagicNumber2 ||
                                 OrderMagicNumber()==MagicNumber3 ||
                                 OrderMagicNumber()==MagicNumber4)
                                    {
                                       if(OrderProfit()>0)
                                          {
                                             if(OrderType()==OP_BUY) {OrderSend(OrderSymbol(),OP_BUY,OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),3,0,0,"Emergency Double",E_MagicNumber);}
                                             if(OrderType()==OP_SELL){OrderSend(OrderSymbol(),OP_SELL,OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),3,0,0,"Emergency Double",E_MagicNumber);}
                                          }
                                    }
            }
   enable_emergency_trading=false;        
   }
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----

//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
  
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----(100 * Close[0] / iClose(NULL,PERIOD_D1,1)) - 100
double d_c1,d_c2,d_c3,d_c4,d_c11,d_c22,d_c33,d_c44;
d_c1=(100*iClose(C1,NULL,0)/iClose(C1,PERIOD_D1,1))-100;
d_c2=(100*iClose(C2,NULL,0)/iClose(C2,PERIOD_D1,1))-100;
d_c3=(100*iClose(C3,NULL,0)/iClose(C3,PERIOD_D1,1))-100;
d_c4=(100*iClose(C4,NULL,0)/iClose(C4,PERIOD_D1,1))-100;

d_c11=(100*iClose(C1,PERIOD_D1,1)/iClose(C1,PERIOD_D1,2))-100;
d_c22=(100*iClose(C2,PERIOD_D1,1)/iClose(C2,PERIOD_D1,2))-100;
d_c33=(100*iClose(C3,PERIOD_D1,1)/iClose(C3,PERIOD_D1,2))-100;
d_c44=(100*iClose(C4,PERIOD_D1,1)/iClose(C4,PERIOD_D1,2))-100;

//check for profit in PIP, and close if the goal is reached
if(show_profit==true)
   {
   double profit1,profit2,profit3,profit4;
   int totalprofit;
   int profitcheck=OrdersTotal();
      for (int tr=0;tr<profitcheck;tr++)
         {
         OrderSelect(tr, SELECT_BY_POS, MODE_TRADES);
            if(OrderMagicNumber()==MagicNumber1)
               {
               if(OrderType()==OP_BUY) {profit1=(MarketInfo(OrderSymbol(),MODE_BID)-OrderOpenPrice())/MarketInfo(OrderSymbol(),MODE_POINT);}
               if(OrderType()==OP_SELL){profit1=(OrderOpenPrice()-MarketInfo(OrderSymbol(),MODE_ASK))/MarketInfo(OrderSymbol(),MODE_POINT);}
               }
              
            if(OrderMagicNumber()==MagicNumber2)
               {
               if(OrderType()==OP_BUY) {profit2=(MarketInfo(OrderSymbol(),MODE_BID)-OrderOpenPrice())/MarketInfo(OrderSymbol(),MODE_POINT);}
               if(OrderType()==OP_SELL){profit2=(OrderOpenPrice()-MarketInfo(OrderSymbol(),MODE_ASK))/MarketInfo(OrderSymbol(),MODE_POINT);}
               }
                
            if(OrderMagicNumber()==MagicNumber3)
               {
               if(OrderType()==OP_BUY) {profit3=(MarketInfo(OrderSymbol(),MODE_BID)-OrderOpenPrice())/MarketInfo(OrderSymbol(),MODE_POINT);}
               if(OrderType()==OP_SELL){profit3=(OrderOpenPrice()-MarketInfo(OrderSymbol(),MODE_ASK))/MarketInfo(OrderSymbol(),MODE_POINT);}
               }
              
            if(OrderMagicNumber()==MagicNumber4)
               {
               if(OrderType()==OP_BUY) {profit4=(MarketInfo(OrderSymbol(),MODE_BID)-OrderOpenPrice())/MarketInfo(OrderSymbol(),MODE_POINT);}
               if(OrderType()==OP_SELL){profit4=(OrderOpenPrice()-MarketInfo(OrderSymbol(),MODE_ASK))/MarketInfo(OrderSymbol(),MODE_POINT);}
               }
            
             //check profit of emergency trades
             int u_orders=OrdersTotal();
             double e_profit=0;
             for (int h=0;h<=u_orders;h++)  
               {
                 OrderSelect(h, SELECT_BY_POS, MODE_TRADES);
                   if(OrderMagicNumber()==E_MagicNumber)
                     {
                       if(OrderType()==OP_BUY) {e_profit+=(MarketInfo(OrderSymbol(),MODE_BID)-OrderOpenPrice())/MarketInfo(OrderSymbol(),MODE_POINT);}
                       if(OrderType()==OP_SELL){e_profit+=(OrderOpenPrice()-MarketInfo(OrderSymbol(),MODE_ASK))/MarketInfo(OrderSymbol(),MODE_POINT);}
                      }
               }
                    
         }
         totalprofit=profit1+profit2+profit3+profit4+e_profit;
         if(enable_emergency_trading==true && totalprofit<=-emergency_loss){doubleorders();}
         if(enable_profit==true && totalprofit>=profit){closeorders();}
         if(enable_loss==true && totalprofit<=-loss){closeorders();}
   }
//end check for profit



Comment("\n",
C1+" Deviation: "+d_c1+" | Previous Deviation: "+d_c11,
"\n",C2+" Deviation: "+d_c2+" | Previous Deviation: "+d_c22,
"\n",C3+" Deviation: "+d_c3+" | Previous Deviation: "+d_c33,
"\n",C4+" Deviation: "+d_c4+" | Previous Deviation: "+d_c44,
"\n",
"\n",C1+"   "+C2+" Pair Deviation: "+(d_c1+d_c2),
"\n",C1+"   "+C3+" Pair Deviation: "+(d_c1-d_c3),
"\n",C1+"   "+C4+" Pair Deviation: "+(d_c1-d_c4),
"\n",C2+"   "+C3+" Pair Deviation: "+(d_c2+d_c3),
"\n",C3+"   "+C4+" Pair Deviation: "+(d_c3-d_c4),
"\n",C2+"   "+C4+" Pair Deviation: "+(d_c2+d_c4),
"\n",
"\n",C1+"/"+C2+" vs. "+C3+"/"+C4+" Pair Deviation: "+((d_c1+d_c2)+(d_c3-d_c4)),
"\n","PIP Profit: "+totalprofit );


//close orders after one Day
if(Hour()>=23)
   {
      int close_ord=OrdersTotal();
         for (int qe=0;qe<close_ord;qe++)
            {
               OrderSelect(qe, SELECT_BY_POS, MODE_TRADES);
                 if( OrderMagicNumber()==MagicNumber1  ||
                     OrderMagicNumber()==MagicNumber2  ||
                     OrderMagicNumber()==MagicNumber3  ||
                     OrderMagicNumber()==E_MagicNumber ||  
                     OrderMagicNumber()==MagicNumber4)
                     {
                     if(OrderType()==OP_BUY) {OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),3);Sleep(2000);}
                     if(OrderType()==OP_SELL){OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),3);Sleep(2000);}
                     }
            }
            closeorders();
   }
//end close orders





//check for opened positions, do not continue if positions are opened
int ord_cnt1=OrdersTotal();
for (int start1=0;start1<ord_cnt1;start1++)  
   {
      OrderSelect(start1, SELECT_BY_POS, MODE_TRADES);
      if(OrderMagicNumber()==MagicNumber1  ||
         OrderMagicNumber()==MagicNumber2  ||
         OrderMagicNumber()==MagicNumber3  ||
         OrderMagicNumber()==E_MagicNumber ||
         OrderMagicNumber()==MagicNumber4)
         {return(0);}
   }

int ticket1,ticket2,ticket3,ticket4;
  //if(trade==true)
  if(Hour()>=0 && Hour()<1 && (Minute()>=5 && Minute()<=12))//start of a new day
   {

      //turn on emergency_exit
      enable_emergency_trading=true;

      if(trade==true && d_c11>0 && IsTradeAllowed()==true) //Previous Day's Deviation is Positive
         {
            //LONG EURUSD
            RefreshRates();
            ticket1=OrderSend(C1,OP_BUY,lot,MarketInfo(C1,MODE_ASK),3,0,0,"Hedge"+C1,MagicNumber1);
            if (ticket1<0){verifyorder(C1,MagicNumber1,"LONG");}Sleep(5000);

            //LONG USDCHF
            RefreshRates();
            ticket2=OrderSend(C2,OP_BUY,lot,MarketInfo(C2,MODE_ASK),3,0,0,"Hedge"+C2,MagicNumber2);
            if (ticket2<0){verifyorder(C2,MagicNumber2,"LONG");}Sleep(5000);

            //SHORT GBPUSD
            RefreshRates();
            ticket3=OrderSend(C3,OP_SELL,lot,MarketInfo(C3,MODE_BID),3,0,0,"Hedge"+C3,MagicNumber3);
            if (ticket3<0){verifyorder(C3,MagicNumber3,"SHORT");}Sleep(5000);

            //LONG AUDUSD
            RefreshRates();
            ticket4=OrderSend(C4,OP_BUY,lot,MarketInfo(C4,MODE_ASK),3,0,0,"Hedge"+C4,MagicNumber4);
            if (ticket4<0){verifyorder(C4,MagicNumber4,"LONG");}Sleep(5000);
         }


      if(trade==true && d_c11<0 && IsTradeAllowed()==true) //Previous Day's Deviation is Negative
         {
            //LONG EURUSD
            RefreshRates();
            ticket1=OrderSend(C1,OP_SELL,lot,MarketInfo(C1,MODE_BID),3,0,0,"Hedge"+C1,MagicNumber1);
            if (ticket1<0){verifyorder(C1,MagicNumber1,"SHORT");}Sleep(5000);

            //LONG USDCHF
            RefreshRates();
            ticket2=OrderSend(C2,OP_SELL,lot,MarketInfo(C2,MODE_BID),3,0,0,"Hedge"+C2,MagicNumber2);
            if (ticket2<0){verifyorder(C2,MagicNumber2,"SHORT");}Sleep(5000);

            //SHORT GBPUSD
            RefreshRates();
            ticket3=OrderSend(C3,OP_BUY,lot,MarketInfo(C3,MODE_ASK),3,0,0,"Hedge"+C3,MagicNumber3);
            if (ticket3<0){verifyorder(C3,MagicNumber3,"LONG");}Sleep(5000);

            //LONG AUDUSD
            RefreshRates();
            ticket4=OrderSend(C4,OP_SELL,lot,MarketInfo(C4,MODE_BID),3,0,0,"Hedge"+C4,MagicNumber4);
            if (ticket4<0){verifyorder(C4,MagicNumber4,"SHORT");}Sleep(5000);
         }
   }

  
//----
   return(0);
  }
//+------------------------------------------------------------------+
 
fregat555 #:

Добрый вечер, день!

У меня  советник на МТ4, не 5. За основу взял известный советник хеджирования НТН. Ошибка переполнения срабатывает не постоянно, периодически.

Ниже его код:

void closeorders()
   {
      int close_ord1=OrdersTotal();
         for (int qe1=0;qe1<close_ord1;qe1++)
            {
               OrderSelect(qe1, SELECT_BY_POS, MODE_TRADES);
                 if( OrderMagicNumber()==MagicNumber1  ||
                     OrderMagicNumber()==MagicNumber2  ||
                     OrderMagicNumber()==MagicNumber3  ||
                     OrderMagicNumber()==E_MagicNumber ||
                     OrderMagicNumber()==MagicNumber4)
                     {
     if(OrderType()==OP_BUY) {RefreshRates();OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),3);Sleep(2000);}
     if(OrderType()==OP_SELL){RefreshRates();OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),3);Sleep(2000);}
                     }
            }
   closeordersverify();        
   return;        
   }
//-------------------------------------------------------------------------------------------------------------------------------- 
 void closeordersverify()
   {
      int close_ord11=OrdersTotal();
         for (int qe11=0;qe11<close_ord11;qe11++)
            {
               OrderSelect(qe11, SELECT_BY_POS, MODE_TRADES);
                 if( OrderMagicNumber()==MagicNumber1  ||
                     OrderMagicNumber()==MagicNumber2  ||
                     OrderMagicNumber()==MagicNumber3  ||
                     OrderMagicNumber()==E_MagicNumber ||
                     OrderMagicNumber()==MagicNumber4)
                     {closeorders();}
                     //if(OrderType()==OP_BUY) {OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),3);Sleep(2000);}
                     //if(OrderType()==OP_SELL){OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),3);Sleep(2000);}
            }
   return;        
   }  

Самое начало вашего кода. Дальше смотреть не стал.

closeorders() может вызывать closeordersverify(), а closeordersverify() может вызывать closeorders(). Вполне вероятно, что при каких-то обстоятельствах эти функции начинают бесконечно вызывать друг друга.

Проверьте подобные места.

 

Я бы не был уверен, что после закрытия ордера (и даже после Sleep(2000)) тот закрытый ордер пропадет из MODE_TRADES. Очень вероятно, что вы закрыли ордер в closeorders(), вызвали closeordersverify(), а там тот ваш закрытый ордер все еще благополучно присутствует в MODE_TRADES и вы снова вызываете closeorders(), а потом снова closeordersverify(), и так без конца

 
Спасибо Владислав, проверю в понедельник, в работе.