Ошибки, баги, вопросы - страница 417

 
joo:

да, если нужно что то вернуть в return().

или хотя бы так, что бы компилятор был уверен, что функция обязательно что то вернет:

это справедливо не только для
switch

но и вообще, для всех функций, кроме void

попробуйте скомпилировать этот код:

//+----------------------------------------------------------------------------+
//|                                                                  Scale.mqh |
//|                                             Copyright © 2010, JQS aka Joo. |
//|                                           http://www.mql4.com/ru/users/joo |
//|                                        https://www.mql5.com/ru/users/joo |
//——————————————————————————————————————————————————————————————————————————————
double Scale(double In,double InMIN,double InMAX,double OutMIN,double OutMAX)
{
  if (OutMIN==OutMAX)
    return(OutMIN);
  if (InMIN==InMAX)
    return((OutMIN+OutMAX)/2.0);
  else
  {
    if (In<InMIN)
      return(OutMIN);
    if (In>InMAX)
      return(OutMAX);
    //return(((In-InMIN)*(OutMAX-OutMIN)/(InMAX-InMIN))+OutMIN);
  }
}
//——————————————————————————————————————————————————————————————————————————————

не компилируется.

а теперь раскоментируйте:

//return(((In-InMIN)*(OutMAX-OutMIN)/(InMAX-InMIN))+OutMIN);

и произойдет чудо! :)

 
Yedelkin:

По Справочнику bool - особый тип, отличный от целочисленных... Поэтому своё неверное утверждение удалил. Хотя спорить не буду - не спец.

Я имел в виду не метки case, а именно перечисления (рассматривая тип bool как самый малочисленный их них). Вот пример с той же самой ошибкой компиляции:

 Поэтому повторю вопрос применительно к этому примеру: Вы хотите сказать, что компилятор не учитывает список значений из перечисления Triple  и их общее количество? У меня все значения из перечисления использованы в операторе switch.

Компилятор (разработчики) перестраховываются как я понял. Суть в том что если переменная явно не инициализирована ей присовится значение false/0  в зависимости от типа (к перечислениям относится второе).

Но вот если в качестве параметра попадет значение выходящее за пределы возможных вариантов (в примере с Triple это могут быть любые значения не пренадлежащие диаразону -1 - +1) при выполнении без деваултного результата возникнут серьезные проблемы.

 
Interesting:

Что должна будет вернуть функция если исключить дефаулный вариант?

Думаю, что последнее значение из перечисления ENUM_CHART_MODE. Сейчас проверю.

...М-дя, не получилось. ПЕчатает следующее: ChartMode=ENUM_CHART_MODE::-1 
 
Interesting:

Компилятор (разработчики) перестраховываются как я понял. Суть в том что если переменная явно не инициализирована ей присовится значение false/0  в зависимости от типа (к перечислениям относится второе).

Но вот если в качестве параметра попадет значение выходящее за пределы возможных вариантов (в примере с Triple это могут быть любые значения не пренадлежащие диаразону -1 - +1) при выполнении без деваултного результата возникнут серьезные проблемы.

Дело не совсем в этом. Посмотрите мой предыдущий пост.
 
joo:
Дело не совсем в этом. Посмотрите мой предыдущий пост.

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

Другое дело если возвращать значение не требуется.

 
Yedelkin:

Думаю, что последнее значение из перечисления ENUM_CHART_MODE. Сейчас проверю.

...М-дя, не получилось. ПЕчатает следующее: ChartMode=ENUM_CHART_MODE::-1 

Если хотите разобраться глубоко во всех таких хитросплетениях, почитайте Бъерна Страуструпа, С++.

Я, если честно, даже не читал документацию особо по MQL5 - просто пишу как на С++. Разработчики довольно точно следуют стандартам этого языка.

 

Добрый день!

build 466.

Запускаю, как только появляется соединение и закачивается  несколько килобайт, терминал закрывается. Отключаю инет - не закрывается.

Прикрепляю файл из каталога /logs/Crash/

Проблема имеет решение?

Спасибо 

 

)) не прикрепляется. Вот текст:

  

Time        : 2011.06.16 10:28 (0:00:11)

Program     : Client Terminal

Version     : 500.466 (09 Jun 2011)

Revision    : 32925

OS          : Windows 7 Professional Service Pack 1 (Build 7601)

Processors  : 2 x AMD Athlon 64 X2 Dual Core Processor 5000+

Memory      : 911 free of 1983 Mb

Virtual     : 1815 free of 2047 Mb

CrashMD5    : 2219A3BB7215B179256A7E41D40BD511

Exception   : C0000094 at 007B41B4 NA to 00000000


Modules     : 00400000 00B96000 terminal.exe (5.0.0.466)

            : 6FDC0000 00027000 wlidnsp.dll (7.250.4225.0)


007B41A0:00014 [007B41B4] #22663 (terminal.exe)

774D58FC:00C74 [774D6570] strcspn (ntdll.dll)

774D58FC:00CAA [774D65A6] strcspn (ntdll.dll)

74A5DC14:000EC [74A5DD00] func_0x74A5DC14 (dbghelp.dll)

74A5E10D:0016E [74A5E27B] SymGetLineFromAddr64 (dbghelp.dll)

74A5F73A:0085A [74A5FF94] func_0x74A5F73A (dbghelp.dll)

74A6189C:000D2 [74A6196E] func_0x74A6189C (dbghelp.dll)

74A5F73A:00A54 [74A6018E] func_0x74A5F73A (dbghelp.dll)

74A5DC14:000EC [74A5DD00] func_0x74A5DC14 (dbghelp.dll)

74A5E10D:0016E [74A5E27B] SymGetLineFromAddr64 (dbghelp.dll)

74A5F73A:0085A [74A5FF94] func_0x74A5F73A (dbghelp.dll)

74A6189C:000D2 [74A6196E] func_0x74A6189C (dbghelp.dll)

74A5F73A:00A54 [74A6018E] func_0x74A5F73A (dbghelp.dll)

774D68C7:000E0 [774D69A7] RtlLogStackBackTrace (ntdll.dll)

774D58FC:004D7 [774D5DD3] strcspn (ntdll.dll)


Registers   : EAX=00000000  EIP=007B41B4  EFLGS=00010246  ES=0023

            : EBX=00000000  ESP=0012E2CC  EBP=0012E320    FS=003b

            : ECX=00000000  ESI=04C74C48  CS=001b         GS=0000

            : EDX=00000000  EDI=00000007  DS=0023         SS=0023 

 

Продолжая тему про использование оператора switch в функциях, возвращающих значения. Вчера был получен и подтверждён промежуточный вывод о том, что при связке "перечисления+switch" использование  метки default становится обязательным. Но вот пример, когда этот вывод опровергается:

enum Triple
  {
   err=-1,
   no = 0,
   hay= 1
  };
Triple triple_var1,triple_var2;
Triple Test(void)
  {
   switch(triple_var1)
     {
      case  err: return(err);
      case   no: return(no);
      case  hay: return(hay);
      default:
         switch(triple_var2)
           {
            case  err: return(err);
            case   no: return(no);
            case  hay: return(hay);
           }
     }
  }
void OnStart()
  {
   Test();
  }
Здесь оператор switch применён дважды, и при повторном его применении ( 2-ой уровень) исключена метка default. Тот же оператор, тот же компилятор, - но работает. Если исходить из предположений, что компилятор учитывает возможность нахождения в переменных triple_var1 и triple_var2 всякого мусора и одновременно не учитывает список значений из перечисления Triple  и их количество, то почему на 2-ом уровне использования оператора switch компилятор не сообщает об ошибке? Наши промежуточные выводы/предположения были неверны или же компилятор ограничивается проверкой операторов только "на 1-ом уровне"? В частности, если закомментировать метку/метки из switch(triple_var2), то никаких сообщений об ошибках всё равно не будет, хотя функция Test() не относится к типу void.

Аналогичный результат получается, если оператор switch(triple_var2) (без метки default) вставить после любой метки case в операторе switch(triple_var1).

 
Yedelkin:

Продолжая тему про использование оператора switch в функциях, возвращающих значения. Вчера был получен и подтверждён промежуточный вывод о том, что при связке "перечисления+switch" использование  метки default становится обязательным. Но вот пример, когда этот вывод опровергается:

Здесь оператор switch применён дважды, и при повторном его применении ( 2-ой уровень) исключена метка default. Тот же оператор, тот же компилятор, - но работает. Если исходить из предположений, что компилятор учитывает возможность нахождения в переменных triple_var1 и triple_var2 всякого мусора и одновременно не учитывает список значений из перечисления Triple  и их количество, то почему на 2-ом уровне использования оператора switch компилятор не сообщает об ошибке? Наши промежуточные выводы/предположения были неверны или же компилятор ограничивается проверкой операторов только "на 1-ом уровне"? В частности, если закомментировать метку/метки из switch(triple_var2), то никаких сообщений об ошибках всё равно не будет, хотя функция Test() не относится к типу void.

 

Это наша недоработка, спасибо за находку, исправим. Будет выдаваться ошибка.
Проверка switch на покрытие в case всех возможных значений, выходит за рамки компиляции.
Как "фича" MQL5 это интересно, мы подумаем что можно сделать.
 
Ошибка исправлена.
"Фичу" проверки switch обсудили, реализовать правильный/корректный контроль невозможно.
Значение выражения switch может быть любым, например:

enum EV { v1, v2, };

string Test(void)
  {
   switch(EV(3))
     {
      case v1: return("v1");
      case v2: return("v2");
     }
   return("oops");
  }
  
void OnStart()
  {
   Print(Test());
  }
Причина обращения: