Скачать MetaTrader 5

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

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
andreybs
609
andreybs  

Добрый день!

Кто нибудь сталкивался с ситуацией, когда код советника внутри DLL вызывает ошибку и она не экранируется стандартными средствами языка, на котором написана DLL?

У меня такое случилось. Есть в DLL одна строчка, которая вызывает ошибку. Найти ошибку не проблема. Проблема в том, что не срабатывает конструкция:

try{ строчка программы с ошибкой... }
catch(...){ last_error=1; }

Терминал просто не запускается. А так работает:

try{ /*строчка программы с ошибкой...*/ }
catch(...){ last_error=1; }

Выходит, try-catch не экранирует exception внутри DLL. А хотелось бы их обрабатывать самому... Есть идеи, почему такое происходит?

Vadim Zhunko
5226
Vadim Zhunko  

У меня это работает. Как Вы выводите сообщение?

В общем виде экспортируемая функция выглядит у меня так:

EXPFUNC INT WINAPI iBarsFastT()
 {
  try
   {
    Init();
    return(Utils::PSingleton<g_TimeTS>::GetInstance()->iBars(Utils::PSingleton<MT4::Path>::GetInstance()->GetServer(), szSymbol, nTimeFrame));
   }
  catch(tstring &sExclusion)
   {
    Utils::Debugging::MessageBoxStop(_T("iBarsFastT()"), sExclusion);
    return(-1);
   }
  catch(TCHAR* szExclusion)
   {
    Utils::Debugging::MessageBoxStop(_T("iBarsFastT()"), szExclusion);
    return(-1);
   }
  catch(...)
   {
    Utils::Debugging::MessageBoxStop(_T("iBarsFastT()"), _T("Системная ошибка!") + Utils::Debugging::TextError());
    return(-1);
   }
 }
Мои сообщения имеют тип TCHAR и std::string. Остальные ловлю отдельно на (...).
andreybs
609
andreybs  
Zhunko:
У меня это работает. Как Вы выводите сообщение?

Я его вообще не вывожу. Я записываю код ошибки:

__declspec(dllexport) double __stdcall iGetRateValue(int ID, char *Symbol, int Period, int rType, int nBar){
ERR_CODE = ERR_NONE;
try{ return Main.GetRateValue(ID,Symbol,Period,rType,nBar); }catch(...){ ERR_CODE = ERR_GET_RATE_VALUE; return NUM_NA; }
}


Потом из терминала можно считать код ошибки через функцию:

__declspec(dllexport) int __stdcall iGetLastError(){
return ERR_CODE;
}

Так вот если Main.GetRateValue(ID,Symbol,Period,rType,nBar); падает с ошибкой, то терминал не запускается вообще. Что-то странное. Может настройки компилятора в VS2010 неверные для обработки exceptions?...

Dmitry Fedoseev
44506
Dmitry Fedoseev  
Обрабатывайте исключение в Main.GetRateValue().
Алексей
63
Алексей  
andreybs:

Добрый день!

Кто нибудь сталкивался с ситуацией, когда код советника внутри DLL вызывает ошибку и она не экранируется стандартными средствами языка, на котором написана DLL?

У меня такое случилось. Есть в DLL одна строчка, которая вызывает ошибку. Найти ошибку не проблема. Проблема в том, что не срабатывает конструкция:

try{ строчка программы с ошибкой... }
catch(...){ last_error=1; }

...

Выходит, try-catch не экранирует exception внутри DLL. А хотелось бы их обрабатывать самому... Есть идеи, почему такое происходит?

Терминал тут не причём. Про "не экранируется стандартными средствами языка", тем более С++, тем более от микрософта вы очень погорячились. С++ практически бездонен.

try{}catch{} в cpp ловит только cpp-шные исключения, которые явно бросаются через throw. У вас судя по всему исключение системное, а оно вызывается другими механизмами. Его надо ловить с помощью SEH, который __try{}__except{} - http://msdn.microsoft.com/en-us/library/ms680657(VS.85).aspx и вообще http://social.msdn.microsoft.com/Search/en-us?query=seh

Могу предположить, что вы пытаетесь ловить исключение, которое вызывается вашей DLL из-за попыток чтения/записи за границами переданных в неё из терминала данных. Это частый источник исключений, и нужно очень внимательно следить за длинами массивов и указателями.

Успеха.

andreybs
609
andreybs  

Gorinych:

... из-за попыток чтения/записи за границами переданных в неё из терминала данных...


Вы совершенно правы - ошибка именно этого типа. Было обращение к объекту по невалидному указателю, т.е. чтение памяти за пределами рабочего стека. Идея про SEH хорошая, пошел читать статью... Кстати, __try{}__except{} экранирует вообще все ошибки или только системные?
Алексей
63
Алексей  

Честно говоря, я не понимаю, что подразумевается под "всеми ошибками". Если вы имеете в виду С++-ные исключения, то SEH их не ловит. И более того, в пределах одной функции нельзя мешать __try{}__except{} и try{}catch{}, это разные механизмы, которые пересекаются по некоторым общим деталям реализации.

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

Алексей
63
Алексей  

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

http://msdn.microsoft.com/en-us/library/4t3saedz.aspx

http://msdn.microsoft.com/en-us/library/5skw957f.aspx

Успеха!

Андрей
1890
Андрей  
А что, вам так нравится программировать с ошибками в памяти?
Как бы... можно программировать и без них. Вообще.
andreybs
609
andreybs  
Gorinych:

Честно говоря, я не понимаю, что подразумевается под "всеми ошибками". Если вы имеете в виду С++-ные исключения, то SEH их не ловит. И более того, в пределах одной функции нельзя мешать __try{}__except{} и try{}catch{}, это разные механизмы, которые пересекаются по некоторым общим деталям реализации.

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


Да, Вы правы - SEH сработал. И да, я имел ввиду C++-ные исключения. Основной тип ошибок, который может возникать в моей DLL-это ошибки работы с памятью, так что я буду использовать SEH на уровне интерфейса вызова функций DLL, а уже внутри классов можно использовать обычный try-catch (хотя это не обязательно, т.к. на уровне работы классов отладка осуществляется через консольное приложение, где есть дебаггер...).

Спасибо за точный и четкий совет! Приятно иметь дело с профессионалами! ;)

andreybs
609
andreybs  
jartmailru:
А что, вам так нравится программировать с ошибками в памяти?
Как бы... можно программировать и без них. Вообще.

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