обработка Exceptions внутри DLL советника - страница 2

 
andreybs:

Не все функции можно отладить через консольное приложение. Ошибки возникают при отладке, а не во время работы приложения...
Да? а про какое консольное приложение я писал?
Возникновение ошибок также описано достаточно интригующе...
.
Я приложил исходник. При ошибке генерируется исключение которое можно поймать try / catch.
.
Впрочем, больше вам мешать не буду.
 

Я там наверно малость попутал, чуть выше пост гляньте, возможно SEH и не нужен, достаточно catch(...){}

Кроме того, SEH во многом - наследие С, и, в частности, он по крайней мере в некоторых случаях не вызывает деструкторы.

Вообще, ловить ошибки конечно же надо, но стоит добиваться, чтобы их вообще не было. Неверное обращение к памяти это однозначный сигнал об ошибке в алгоритме и падение системы может быть ещё настоящий пустяк в сравнении с тем, что бажный алго будет открывать покупки там, где надо открывать продажи ;)

Успеха.

 
Gorinych:

ps: да, забыл, С++-ные вроде таки могут ловить SEH исключения через catch(...){}, (реальное троеточие в аргументе catch) поэтому посмотрите сначала в эту сторону, скорее всего разбираться с SEH не потребуется.



неа, catch(...) не ловит такие ошибки...
 
andreybs:

неа, catch(...) не ловит такие ошибки...

Ага, понятно, да... Этож системное исключение, может типа ACCESS_VOILATION, а они да, только SEH'ом. Давно я ними уже не сталкивался.

зы: если хотите ещё совет - пишите юнит-тесты на каждый алго. Это занимает мало времени, но экономит массу сил и нервов.

 
jartmailru:
Да? а про какое консольное приложение я писал?
Возникновение ошибок также описано достаточно интригующе...
.
Я приложил исходник. При ошибке генерируется исключение которое можно поймать try / catch.
.
Впрочем, больше вам мешать не буду.

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

Например, если из терминала обратиться к элементу несуществующего буфера одного из индикаторов:
Indicator->Buffer[10]->Value если Indicator->Buffer[1] вернет NULL, то сработает ошибка, которая ловится SEH
Заранее известно кол-во буферов индикатора (известно, что №10 нет). И тем не менее такое обращение возможно. Поэтому некорректные вызовы из терминала нужно обрабатывать на уровне интерфейса DLL (если внутри классов данное обращение не ловится).
 
andreybs:

Не все функции можно отладить через консольное приложение. Ошибки возникают при отладке, а не во время работы приложения...

Абсолютно всё можно отладить через консоль, но надо ли это делать?

SEH лучше не использовать, а ловить ошибки от WinAPI прям рядом с функцией, описывать их самостоятельно и возвращать в throw(). Код привёл выше.

На счёт самостоятельно, есть функция, которая возвращает описание ошибки по её коду на языке ОС. Вот это и ловить.

========

По поводу выхода за пределы памяти, деления на ноль и т.д., тоже не понимаю зачем это допускать? Если уж, Вам это необходимо, расставте по условиям выхода за пределы throw() с описанием.

 
Gorinych:

зы: если хотите ещё совет - пишите юнит-тесты на каждый алго. Это занимает мало времени, но экономит массу сил и нервов.


Ага, поэтому создал 2 проекта сразу - один DLL, другой - консольное приложение, использующее те же исходники, что и DLL. Жаль, что возможности консольного приложения ограничены... Например, сложно сгенерить корректный массив таймсерий, на котором нужно обкатывать алгоритм. Поэтому я задумался над тем, чтобы сделать класс, который позволяет сохранять и загружать массив элементов типа
#pragma pack(push,1)
struct RateInfo
{
unsigned int Time;
double Open;
double Low;
double High;
double Close;
double Volume;
};
#pragma pack(pop)

Можно будет один раз загрузить его из терминала и сохранить в файл, а при тестировании через консольное приложение загружать из файла. Может у Вас есть такой класс? :)
 
Zhunko:

SEH лучше не использовать, а ловить ошибки от WinAPI прям рядом с функцией, описывать их самостоятельно и возвращать в throw(). Код привёл выше.



А чем SEH плох? Ведь код ошибки даже не считаешь, если терминал просто не запускается...

В остальном так и происходит - ловятся критические ошибки, кодируются и в LastError.

Кстати, вывод через MessageBox мне не походит. Ошибка может быть циклической, тогда терминал будет завален месагами...

Что касается ошибок типа деления на нуль и т.п., то их не возникает. Везде встраивается защита от этого на уровне логики.

 
andreybs:

1. А чем SEH плох? Ведь код ошибки даже не считаешь, если терминал просто не запускается...

2. Кстати, вывод через MessageBox мне не походит. Ошибка может быть циклической, тогда терминал будет завален месагами...

1. Не понимаю, почему? У меня запускается и считывается.

2. Обработайте, как Вам надо. Мне этот способ больше нравиться. Можно в лог записывать. Есть мессаджбокс с таймаутом. Будет только одно сообщение в единицу времени по вашему усмотрению.

 
Zhunko:
Не понимаю, почему? У меня запускается и считывается.

Это если ошибка не связана с Access Violation. Иначе терминал падает, что неправильно.

Кстати, может у Вас есть класс, который позволяет сохранять и загружать массив элементов типа
#pragma pack(push,1)
struct RateInfo
{
unsigned int Time;
double Open;
double Low;
double High;
double Close;
double Volume;
};
#pragma pack(pop)
Можно будет один раз загрузить его из терминала и сохранить в файл, а при тестировании через консольное приложение загружать из файла
Причина обращения: