zero divide - страница 2

 

Если хотите локализовать ошибку, отчасти поможет такой "шаблон":

extern bool TraceIsAllowed;                              // Показывать трассировку?
//+------------------------------------------------------------------+
//| XXX
//+------------------------------------------------------------------+
void XXX(string MasterName, string ProgramTrace, string Parameter)
  {
   string SlaveName="XXX";                               // Имя функции.
   ProgramTrace=ProgramTrace+"=>"+SlaveName;             // Путь обращения к функции.
   if( Parameter!="" ) ProgramTrace=ProgramTrace+"("+Parameter+")";
   string Message=ProgramTrace;                          // Функциональные сообщения.
   LastErrorCode=GetLastError();
   if( LastErrorCode>0 )
     {                                                   // Ошибка или некорректные параметры.
      Message=Message+" ERROR "+LastErrorCode+" at Start";
      Message=Message+"";                                // Значения параметров.
      Print(Message); return;                            // Функцию не выполнять.
     }
   if( TraceIsAllowed ) Print(Message);                  // Задана трассировка программы .
//----
   
//----
   LastErrorCode=GetLastError();
   if( LastErrorCode>0 ) Message=Message+" ERROR "+LastErrorCode;
   if( Message!=ProgramTrace )
     {                                                   // Были функциональные сообщения.
      Message=Message+" at Finish";                      // Функция выполнена.
      Message=Message+"";                                // Значения параметров.
      Print(Message);                                    // Печать функциональных сообщений.
     }
   return;
  }
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
   string SlaveName="Init";                              // Имя функции.
   string ProgramTrace=SlaveName;                        // Путь обращения к функции.
   string Message=ProgramTrace;                          // Функциональные сообщения.
   LastErrorCode=GetLastError();
   if( LastErrorCode>0 )
     {                                                   // Ошибка или некорректные параметры.
      Message=Message+" ERROR "+LastErrorCode+" at Start";
      Print(Message); return(0);                         // Функцию не выполнять.
     }
   if( TraceIsAllowed ) Print(Message);                  // Задана трассировка программы .
//----
   
//----
   LastErrorCode=GetLastError();
   if( LastErrorCode>0 ) Message=Message+" ERROR "+LastErrorCode;
   if( Message!=ProgramTrace )
     {                                                   // Были функциональные сообщения.
      Message=Message+" at Finish";                      // Функция выполнена.
      Print(Message);                                    // Печать функциональных сообщений.
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   string SlaveName="Start";                             // Имя функции.
   string ProgramTrace=SlaveName;                        // Путь обращения к функции.
   string Message=ProgramTrace;                          // Функциональные сообщения.
   LastErrorCode=GetLastError();
   if( LastErrorCode>0 )
     {                                                   // Ошибка или некорректные параметры.
      Message=Message+" ERROR "+LastErrorCode+" at Start";
      Print(Message); return(0);                         // Функцию не выполнять.
     }
   if( TraceIsAllowed ) Print(Message);                  // Задана трассировка программы .
//----
   
//----
   LastErrorCode=GetLastError();
   if( LastErrorCode>0 ) Message=Message+" ERROR "+LastErrorCode;
   if( Message!=ProgramTrace )
     {                                                   // Были функциональные сообщения.
      Message=Message+" at Finish";                      // Функция выполнена.
      Print(Message);                                    // Печать функциональных сообщений.
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
   string SlaveName="DeInit";                            // Имя функции.
   string ProgramTrace=SlaveName;                        // Путь обращения к функции.
   string Message=ProgramTrace;                          // Функциональные сообщения.
   LastErrorCode=GetLastError();
   if( LastErrorCode>0 )
     {                                                   // Ошибка или некорректные параметры.
      Message=Message+" ERROR "+LastErrorCode+" at Start";
      Print(Message); return(0);                         // Функцию не выполнять.
     }
   if( TraceIsAllowed ) Print(Message);                  // Задана трассировка программы .
//----
   
//----
   LastErrorCode=GetLastError();
   if( LastErrorCode>0 ) Message=Message+" ERROR "+LastErrorCode;
   if( Message!=ProgramTrace )
     {                                                   // Были функциональные сообщения.
      Message=Message+" at Finish";                      // Функция выполнена.
      Print(Message);                                    // Печать функциональных сообщений.
     }
   return(0);
  }
*/
//+------------------------------------------------------------------+
 
prorab:

Не обязательно деление на ноль.

У меня была сборка с несколькими #include <***.mqh>  и, когда в тексте основного модуля я неправильно обратился к одной функции,

то компиляция прошла нормально, а при работе эксперта, в журнале стала проскакивать эта ошибка.

Подробностей уже не помню, давно было, но причину нашел с большим трудом. 


Это другое - ошибка при "позднем связывании". В этом случае работа программы также прерывается, но при новом тике не возобновляется, а возобновляется при повторной инициализации.


https://docs.mql4.com/ru/runtime/imports

 
tara:

Потому, что при делении на ноль выполнение программы немедленно прерывается.

https://docs.mql4.com/ru/runtime/errors

Нет, НЕ прерывается. Я провел простой эксперимент. Вставил следующий код сразу перед окончанием функции start():

  // test zero divide
  int nltestZD, nltest0=0;
  nltestZD =  5 / nltest0;

Эксперт... РАБОТАЕТ!

В логе:

2013.01.19 01:12:42 2012.05.29 00:00  e-<skipped>: start() 1 ERR=4013 ERR_ZERO_DIVIDE                dt=2012.05.29 00:00
2013.01.19 01:12:42 2012.05.29 00:00  e-<skipped>: ... ... <info>
2013.01.19 01:12:42 2012.05.28 23:59  e-<skipped>: zero divide
2013.01.19 01:12:42 2012.05.28 23:58  e-<skipped>: zero divide

То есть, деление на ноль не должно вышибать эксперта, а мой код должен ловить эту ошибку и, как видим, ловит.

А вот если не ловит, то почему???

 
mt4trade:

Нет, НЕ прерывается. Я провел простой эксперимент. Вставил следующий код сразу перед окончанием функции start():

  // test zero divide
  int nltestZD, nltest0=0;
  nltestZD =  5 / nltest0;

Эксперт... РАБОТАЕТ!

В логе:

2013.01.19 01:12:42 2012.05.29 00:00  e-<skipped>: start() 1 ERR=4013 ERR_ZERO_DIVIDE                dt=2012.05.29 00:00
2013.01.19 01:12:42 2012.05.29 00:00  e-<skipped>: ... ... <info>
2013.01.19 01:12:42 2012.05.28 23:59  e-<skipped>: zero divide
2013.01.19 01:12:42 2012.05.28 23:58  e-<skipped>: zero divide

То есть, деление на ноль не должно вышибать эксперта, а мой код должен ловить эту ошибку и, как видим, ловит.

А вот если не ловит, то почему???

Тут ловить нечего! В сомнительных формулах подставляйте защиту от нуля! Например:

double ZeroNo = МаthMax(Ваш знаменатель, 1*Point) и ставьте это ZeroNo на место Вашего знаменателя в Ваших формулах!

 
mt4trade:
mt4trade:

Нет, НЕ прерывается. Я провел простой эксперимент. Вставил следующий код сразу перед окончанием функции start():

  // test zero divide
  int nltestZD, nltest0=0;
  nltestZD =  5 / nltest0;

Эксперт... РАБОТАЕТ!

В логе:

2013.01.19 01:12:42 2012.05.29 00:00  e-<skipped>: start() 1 ERR=4013 ERR_ZERO_DIVIDE                dt=2012.05.29 00:00
2013.01.19 01:12:42 2012.05.29 00:00  e-<skipped>: ... ... <info>
2013.01.19 01:12:42 2012.05.28 23:59  e-<skipped>: zero divide
2013.01.19 01:12:42 2012.05.28 23:58  e-<skipped>: zero divide

То есть, деление на ноль не должно вышибать эксперта, а мой код должен ловить эту ошибку и, как видим, ловит.

А вот если не ловит, то почему???



А вот если не ловит, то почему???

Почитайте документацию по моей ссылке, там много нового и интересного:) Не ловится потому, что при делении на ноль работа была прервана, а при поступлении нового тика - возобновлена. Код ошибки сохранился и был распечатан Вашей программой, но где была ошибка - Вам неведомо:( Подобие шаблона, выложенное мною, по крайней мере, поможет определить, при выполнении какой функции произошла ошибка, но лог будет не детским:)
 
borilunad:

Тут ловить нечего! В сомнительных формулах подставляйте защиту от нуля! Например:

double ZeroNo = МаthMax(Ваш знаменатель, 1*Point) и ставьте это ZeroNo на место Вашего знаменателя в Ваших формулах!

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

... и ставьте это ZeroNo на место Вашего знаменателя в Ваших формулах!


От ошибки это спасёт, но расчёт может увести очень далеко от правды. Лучше всё-таки (в общем случае) остановить вычисления и сообщить о проблеме.

В частных случаях может быть допустимым. 

 
borilunad:

Тут ловить нечего! В сомнительных формулах подставляйте защиту от нуля! Например:

double ZeroNo = МаthMax(Ваш знаменатель, 1*Point) и ставьте это ZeroNo на место Вашего знаменателя в Ваших формулах!

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

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

Шаблон Ваш конечно полезен, но думаю он делает примерно то же, что мой код. Впрочем, поразбираюсь с ним и со ссылкой еще.

 
mt4trade:

Шаблон Ваш конечно полезен, но думаю он делает примерно то же, что мой код. Впрочем, поразбираюсь с ним и со ссылкой еще.

Если надумаете превратить его в полноценный шаблон MQL4, просьба выложить здесь, или в кодобазе.

Делает он действительно почти то же, но с трассировкой.

Причина обращения: