Обработчик ошибок в MQL4 программах.

 
Уважаемые разработчики!
Обработка ошибок в программах на MQL4 имеет важнейшее значение!!!

На данный момент существует единственный метод, с помощью которого можно узнать произошла ошибка или нет, - получить код последней ошибки с помощью функции GetLastError() с последующей обработкой ошибочной ситуации. Отлавливать всевозможные ошибки только с помощью функции GetLastError() затруднительно по следующим соображениям:
  • В программах практически невозможно предусмотреть обработку всех возможных ошибок после каждой строчки кода
  • На этапе кодирования и тестирования необходимо знать обо всех "подводных камнях", которые могут привести к возникновению ошибок, что требует большого опыта в написании MQL4 программ
  • Если не обработать своевременно ошибку, используя GetLastError(), при возникновении следующей ошибки информация о предыдущей ошибке теряется
  • Можно так никогда и не узнать, что во время выполнения программы возникают ошибки, обработка которых не заложена в алгоритме
  • Необходимо просматривать логи в поисках ошибок
Чтобы облегчить жизнь как начинающим так и продвинутым экспертописателям предлагаю улучшить механизм обработки ошибок следующим образом.

В языке имеются функции init(), deinit(), start(). Дополнительно предлагаю ввести в язык функцию, например, error(int errno), которая будет вызываться при возникновении любой ошибки и передавать в качестве параметра номер ошибки.

Что от этого выиграет экспертописатель:
  • Полный контроль над ВСЕМИ ошибками!!! Ни одна ошибка не будет пропущена
  • "Разгрузка" основного кода программы от сложных конструкций обработки ошибок. Обработку ошибок можно будет организовать внутри функции error() или в виде самостоятельной библиотеки, которую можно будет подключать к основной программе
  • Значительно облегчится отладка и тестирование программ. Вывод сообщений о возникновении ошибок можно будет организовать отдельно от основного кода программы
Повлияет ли на работоспособность уже написанных программ предлагаемый механизм обработки ошибок? Абсолютно никак не повлияет, т.к. эти программы ничего не будут знать о существовании предлагаемого механизма

Сложно ли реализовать предлагаемый механизм? На мой взгляд ни каких сложностей с этим нет, достаточно, чтобы исполняющая подсистема клиентского терминала, после присвоения значения специальной переменной last_error, о которой упоминается в документации, вызывала функцию error(int errno) mql4-программы
 
Ваша мысль понятна, но лучше не изобретать колесо в 1001-й раз. Уже давно всё придумано и реализовано в стандартных современных платформах программирования: Java, .NET, C++ и т.д. Это механизм обработки исключений (exceptions).
Или, практически, блоки try-catch-finally.

Если уж развитие MQL4 зайдёт так далеко, то ничего придумывать не надо, остаётся только реализовать это:


Подробнее об этом можно прочитать в MSDN online на http://support.microsoft.com/kb/308345 "How to catch exceptions in Visual C#".
Если хотите читать на русском, купите хорошую книгу, например, эту.
 
Странная какая-то проблема... Программирую почти 1,5 года на MQL4 причём далеко не маленькие эксперты (последний >200кБ в ex4 файле) и потребности в чём-то подобном никогда не испытывал. Может быть проще просто досконально отрабатывать код каждой разрабатываемой функции эксперта вместо того, чтобы изучать возможные ошибки кривонаписанных функций с помощью каких-то дополнительных специальных наворотов? Тем более думаю очень немногим нужно такое нововведение. Хотя это только лишь моё мнение, ни на что не претендующее.
 
strator писал (а):
например, error(int errno), которая будет вызываться при возникновении любой ошибки и передавать в качестве параметра номер ошибки.


То, что Вы предлагаете, тоже давно известно в мировой практике программирования и называется обработкой событий, или, в более ранних вариантах, callback функциями. Второе принято в классическом C++ и Win API функциях, а событийная модель - более новый способ в управляемом коде (java, .net).
Пример в Win API:
BOOL EnumWindows(          
	WNDENUMPROC lpEnumFunc,
	LPARAM lParam
);

Первый параметр - адрес callback (обратно вызываемой) пользовательской функции, которую вызовут из Win API при возникновении события (нахождении ещё одного окна).

Дело в том, что на нужные события нужно подписываться в нужном месте кода, и отписываться от них. Значит, нужно реализовывать в языке и это.
Если же будет просто один обработчик, вызываемый всегда и безусловно при любой ошибке, как узнать, где, в каком месте стека вызова, какой функции эта ошибка произошла, т.е. какой код прервался? В функции start, init, в каком месте? Одного параметра errno тут явно недостаточно.
Не знаю, как это будут решать (возможно) в MQL4, но это непростой вопрос.

Один из интересных способов реализации отслеживания событий приведён в статье "События в МetaТrader 4" 'События в МetaТrader 4'.

 
chv писал (а):

Ваша мысль понятна, но лучше не изобретать колесо в 1001-й раз

Я ничего нового в этом плане не изобретаю, как вы сами сказали:

Уже давно всё придумано и реализовано в стандартных современных платформах программирования: Java, .NET, C++ и т.д.

MQL4 хоть и похож на С++ по синтаксису, но далеко не С++ и тем более не Java, поэтому конструкций типа Try-Catch-Finaly в MQL не будет никогда, разве что терминал MetaTrader5 будет полностью написан на Java и к нему можно будет цеплять скрипты, индюки и экспертов, также написанных на Java. Но это из области фантастики!

как узнать, где, в каком месте стека вызова, какой функции эта ошибка произошла, т.е. какой код прервался? В функции start, init, в каком месте? Одного параметра errno тут явно недостаточно. Не знаю, как это будут решать (возможно) в MQL4, но это непростой вопрос.

Вот это действительно непростой вопрос. В MQL4 его никак не решить, т.к. в откомпилированных MQL-программах не предусмотрено наличие отладочной информации (поэтобу собственно дебаггера до сих пор нет, хотя в эдиторе предусмотрена кнопочка F9-брейкпоинт)

Solandr писал (а):
Может быть проще просто досконально отрабатывать код каждой разрабатываемой функции эксперта вместо того, чтобы изучать возможные ошибки кривонаписанных функций с помощью каких-то дополнительных специальных наворотов?
Вот и приходиться сначала писать код на Builder'e, тестить дебаггером, и только потом перелаживать готовенькое в MQL4.
 
strator писал (а):
Вот и приходиться сначала писать код на Builder'e, тестить дебаггером, и только потом перелаживать готовенькое в MQL4.


Думаю, что это просто вопрос привычки. Люди на самом деле очень консервативны по своей сути. Особенно это касается внедрения чего-либо нового. Если человек привык к дебаггеру, то ему трудно перестроить свои методы отладки на более неудобный ему MetaEditor для MQL4 с его принтованием. Все хотят, чтобы новое было похоже на что-то уже им известное старое. Я например тоже очень консервативен. Я например против ежегодной разработки новых версий операционых систем (буду сидеть на Win2000, настолько насколько это будет вообще только возможно ;o)), так как в каждой новой версии свои особенности, часто убивающие удобство предыдущих версий. Зачем тратить своё драгоценное время, которого не так уж много, на изучение каких-то других методов настройки и подстройки, которые разработчики посчитали нужным внести, если это же самое решалось достаточно просто и в предыдущих версиях операционной системы???
Хотя если разработчики займутся реализацией вашего пожелания, то очень хотелось бы чтобы чрезмерным консерваторам, типа меня не потребовалось бы что-то менять в методике отладки программ, да и в самих программах тоже. То есть чтобы обработка событий не стала обязательным атрибутом написания программ. Оставьте принтование - я к нему очень привык и уже не представляю себе что-то другое для написания советников!
 
Всяк кулик своё болото хвалит...

Мне нравится организация обработчиков ошибок в FoxPro. Там есть команда, которой можно назначить любую функцию или процедуру обработчиком ошибок и эта функция будет вызвана при возникновении ошибки. А чтобы совсем полная ясность была, наличествуют такие функции:
LINENO() - возвращает номер строки, с которой произошёл вызов с определённого уровня,
MESSAGE() - возвращает текущее сообщение об ошибке или строку исходного кода, с которой произошёл вызов определённого уровня,
PROGRAM() - возвращает наименование процедуры или функции с определённого уровня вызова.
Причина обращения: