Какие события вызывают переполнение стека? - страница 2

 
dokpiknik >>:

У меня используется, похоже, "бесполезный" оператор ObjectSet(obj_order, OBJPROP_WIDTH, 1);. "Бесполезный", поскольку, если я не ошибаюсь, линия толщиной 1 рисуется по умолчанию. Верно? (Прошу ответить)

Линия по умолчанию создается со свойствами последней созданной линии.

Т.е. если последней создавалась линия толщиной 1 - следующая создастся такой же.


Вывод: опреатор не бесполезный.

 
komposter писал(а) >>

Линия по умолчанию создается со свойствами последней созданной линии.

Т.е. если последней создавалась линия толщиной 1 - следующая создастся такой же.

Вывод: опреатор не бесполезный.

Большое спасибо за науку, Андрей!

 
dokpiknik >>:

Около 1500 из всего 1850 операторов моего советника находятся в "бесконечном" цикле в модуле int start().

...

Разбивать этот фрагмент программы на функции крайне нежелательно (если только альтернативного решения не найдётся, тут уж ничего не поделаешь), потому что в нём обрабатываются массивы в цикле. Любой из двух возможных вариантов решения проблемы [...] приводят с существенному утяжелению программы и уменьшению скорости обработки.

1500 - многовато, конечно. Если бы это писал я, у меня на такую длину кода было бы порядка 50 небольших функций. И не надо говорить о том, что стоимость вызовов функций настолько велика, что выполнение кода существенно замедляется. Это сказки теоретиков "структурного программирования", 20 лет назад рекомендовавших для повышения быстродействия снова собирать все функции в одну.

Вопрос поднимался на форуме, Rosh выполнил натурные эксперименты по сравнению быстродействия простого кода без функций и оного с функциями, заменяющими некоторые части кода. Разница оказалась минимальной - за исключением тех случаев, когда функции вызывались однократно, а не в цикле.

И всё потому, что в MQL4 не предусмотрены глобальные массивы.

Ну как же это, уважаемый, не предусмотрены? Предусмотрены - и еще как. Объявляются точно так же, как и в Си. Может быть, Вы не умеете их готовить?

P.S. Пардон, пока написал ответ, исходный пост исчез. Но все же я решил оставить ответ. Вот, кстати, моя статистика: на 700 строк кода вместе с комментариями у меня 22 функции. И в коде разбираться намного проще, чем в единой гигантской функции (скажем, через несколько месяцев).

 
dokpiknik писал(а) >>

И всё потому, что в MQL4 не предусмотрены глобальные массивы.

Mathemat писал(а) >>

Ну как же это, уважаемый, не предусмотрены? Предусмотрены - и еще как. Объявляются точно так же, как и в Си. Может быть, Вы не умеете их готовить?

Звучит провокационно. Ну, да ладно. Наше непонимание друг друга имеет источником путаницу понятий глобальная переменная (массив) и глобальная переменная (массив) клиентского терминала, происхождение которой состоит в недостаточной детерминации и локализации этих понятий в документации. Авторы часто используют в контексте понятие глобальная переменная в смысле глобальная переменная клиентского терминала, что категорически недопустимо, потому что приводит к превратному пониманию смысла излагаемого. Представьте, кто бы мог что-нибудь понять, если бы известная монография Фихтенгольца "Курс матанализа" грешила бы подобным...? Избежать путаницы можно, заменив длинное, неудобное понятие глобальная переменная (массив) клиентского терминала, например, понятием суперпеременная (супермассив) или каким-то другим самовыражающимся подходящим словом, чтобы подчеркнуть разную "степень глобализации" двух важных терминов.

Теперь к "моим баранам". Я обеими руками за фрагментацию программы, за разбиение её на несколько небольних функций (преимущества такого подхода очевидны и Вами упомянуты). Из циклов программы start() обращаться к функциям, передавая им элементы массивов (посредством простых переменных) по причине существенного увеличения времени обработки не оптимально. Остаётся два варианта - либо сделать массивы "видимыми" в функции через их "глобализацию" (использовать неудобный способ создания квази-глобальных массивов клиентского терминала, которые являются по сути совокупностью отдельных глобальных переменных клиентского терминала с присвоенными им программистом номерами), либо передавать ИМЕНА МАССИВОВ в функции, замещающие соответствующие формальные параметры функций. Я полагал, что второй вариант не возможен, поскольку в документации указано на то, что в функции допустимо передавать только константы, выражения и переменные. Может быть под переменными авторы документации подразумевают также имена массивов? Так ли это? Помогите разобраться. Спасибо.

Перенёс дискусии в новую тему https://www.mql5.com/ru/forum/116143

 
dokpiknik писал(а) >>

Звучит провокационно. Ну, да ладно....

Вы про какие глобальные массивы? Типа глобальных переменных терминала? Такого нет. На уровене модуля можно объявить массив, он будет виден во всех функциях и не надо будет его передавать как параметр.

 
Integer писал(а) >>

Вы про какие глобальные массивы? Типа глобальных переменных терминала? Такого нет. На уровене модуля можно объявить массив, он будет виден во всех функциях и не надо будет его передавать как параметр.

Спасибо! Согласен полностью, уже разобрался.

 

internal stack overflow-simplify the program

Объявляю массивы, 33 шт., (количество на проблему не влияет, в смысле уменьшения)

   double aJPY[8];

В ините рисую табличку

   // рисуем таблицу фонов
   for(x=0;x<9;x++)
      for(y=0;y<7;y++)
      {
         ObjectCreate("AsignalF"+x+y,OBJ_LABEL,0,0,0,0,0);
         ObjectSet("AsignalF"+x+y,OBJPROP_XDISTANCE,x*54);
         ObjectSet("AsignalF"+x+y,OBJPROP_YDISTANCE,y*56);
         ObjectSetText("AsignalF"+x+y,CharToStr(110),72,"Wingdings",DimGray);
      }
   // рисуем таблицу объектов
   for(x=0;x<9;x++)
      for(y=0;y<29;y++)
      {
         ObjectCreate("signal"+x+y,OBJ_LABEL,0,0,0,0,0);
         ObjectSet("signal"+x+y,OBJPROP_XDISTANCE,x*44+12);
         ObjectSet("signal"+x+y,OBJPROP_YDISTANCE,y*12+21);
         ObjectSetText("signal"+x+y,SymbolNameString[x],8,"Arial",SymbolBasisColor);
      }

В старте заполняю массивы

for(a=0;a<8;a++)
  {aJPY[a]=iCustom(NULL,PERIOD_M15,"Indexes_v8L_JPY",a,0);
   bJPY[a]=iCustom(NULL,PERIOD_M15,"Indexes_v8L_JPY",a,1);
   // все остальные...;}

Может, важно, - сначала было так

   for(a=0;a<8;a++)
   {aJPY[a]=iCustom(NULL,PERIOD_M15,"Indexes_v8L_JPY",a,0);}
   for(a=0;a<8;a++)
   {bJPY[a]=iCustom(NULL,PERIOD_M15,"Indexes_v8L_JPY",a,1);}
   // и т. д.

все шло в своих циклам - изменение на проблему не повлияло.

Заполняю первую строку (отдельно - это названия столбцов) 

   ObjectSetText("signal00",SymbolNameString[0],8,"Arial",SymbolBasisColor);
   ObjectSetText("signal10",SymbolNameString[1],8,"Arial",SymbolBasisColor);

   // 8 шт., из массива string

Заполняю построчно так

ObjectSetText("signal31",DoubleToStr(aJPY[3],3),8,"Arial",SymbolBasisColor);
   if (aJPY[0]>aJPY[3])
   {ObjectSetText("signal01",DoubleToStr(aJPY[0],3),8,"Arial",SymbolSellColor);}
      else
      {ObjectSetText("signal01",DoubleToStr(aJPY[0],3),8,"Arial",SymbolBuyColor);}
   if (aJPY[1]>aJPY[3])
   {ObjectSetText("signal11",DoubleToStr(aJPY[1],3),8,"Arial",SymbolSellColor);}
      else
      {ObjectSetText("signal11",DoubleToStr(aJPY[1],3),8,"Arial",SymbolBuyColor);}
   if (aJPY[2]>aJPY[3])
   {ObjectSetText("signal21",DoubleToStr(aJPY[2],3),8,"Arial",SymbolSellColor);}
      else
      {ObjectSetText("signal21",DoubleToStr(aJPY[2],3),8,"Arial",SymbolBuyColor);}   
   if (aJPY[4]>aJPY[3])
   {ObjectSetText("signal41",DoubleToStr(aJPY[4],3),8,"Arial",SymbolSellColor);}
      else
      {ObjectSetText("signal41",DoubleToStr(aJPY[4],3),8,"Arial",SymbolBuyColor);}   
   if (aJPY[5]>aJPY[3])
   {ObjectSetText("signal51",DoubleToStr(aJPY[5],3),8,"Arial",SymbolSellColor);}
      else
      {ObjectSetText("signal51",DoubleToStr(aJPY[5],3),8,"Arial",SymbolBuyColor);}
   if (aJPY[6]>aJPY[3])
   {ObjectSetText("signal61",DoubleToStr(aJPY[6],3),8,"Arial",SymbolSellColor);}
      else
      {ObjectSetText("signal61",DoubleToStr(aJPY[6],3),8,"Arial",SymbolBuyColor);}
   if (aJPY[7]>aJPY[3])
   {ObjectSetText("signal71",DoubleToStr(aJPY[7],3),8,"Arial",SymbolSellColor);}
      else
      {ObjectSetText("signal71",DoubleToStr(aJPY[7],3),8,"Arial",SymbolBuyColor);}
   {
   if (aJPY[0]>aJPY[3]&&aJPY[1]>aJPY[3]&&aJPY[2]>aJPY[3]&&aJPY[4]>aJPY[3]&&aJPY[5]>aJPY[3]&&aJPY[6]>aJPY[3]&&aJPY[7]>aJPY[3])
   {ObjectSetText("signal81",CharToStr(230),10,"Wingdings",SymbolSellColor);}
   else if (aJPY[0]<aJPY[3]&&aJPY[1]<aJPY[3]&&aJPY[2]<aJPY[3]&&aJPY[4]<aJPY[3]&&aJPY[5]<aJPY[3]&&aJPY[6]<aJPY[3]&&aJPY[7]<aJPY[3])
   {ObjectSetText("signal81",CharToStr(228),10,"Wingdings",SymbolBuyColor);}
   else
   {ObjectSetText("signal81",CharToStr(224),10,"Wingdings",SymbolBasisColor);}
   }

На заполнении очередной (27-ой) строки таким блоком и вылезла ошибка.

На stacksize реакции 0.

Вечный вопрос: что делать? 

 

Убрал заполнение первой строки (отдельно - названия столбцов), они заполняются в ините.

Удалось вставить еще один блок, на следующем - снова ошибка.

Какое ограничение на количество применений ObjectSetText  и простых конструкций типа if else??? 

 

Закомментировал вычисления типа

   {
   if (aJPY[0]>aJPY[3]&&aJPY[1]>aJPY[3]&&aJPY[2]>aJPY[3]&&aJPY[4]>aJPY[3]&&aJPY[5]>aJPY[3]&&aJPY[6]>aJPY[3]&&aJPY[7]>aJPY[3])
   {ObjectSetText("signal81",CharToStr(230),10,"Wingdings",SymbolSellColor);}
   else if (aJPY[0]<aJPY[3]&&aJPY[1]<aJPY[3]&&aJPY[2]<aJPY[3]&&aJPY[4]<aJPY[3]&&aJPY[5]<aJPY[3]&&aJPY[6]<aJPY[3]&&aJPY[7]<aJPY[3])
   {ObjectSetText("signal81",CharToStr(228),10,"Wingdings",SymbolBuyColor);}
   else
   {ObjectSetText("signal81",CharToStr(224),10,"Wingdings",SymbolBasisColor);}
   }

Удалось заполнить таблицу значений.

Начал раскомментировать по очереди - на 5 блоке опять ошибка, причем в строке комментария!

Если когда-нибудь добью и надумаю выложить - так и напишу: разбит на 2 индикатора из-за кривого компилятора. 

 
Andrei01:
Проверте координаты куда выводите может в них ошибка.
Нет. Я же все расписал.