Ошибка при модификации ордера

 

О чём говорит эта ошибка, при модификации ордера экспертом?

2011.11.08 13:25:20   failed prices for  0.00 [Invalid request]

 
1Serg:

О чём говорит эта ошибка, при модификации ордера экспертом?

2011.11.08 13:25:20   failed prices for  0.00 [Invalid request]

Разобрался, добавил ZeroMemory после объявления структуры и ошибка пропала.

Документация по MQL5: Основы языка / Типы данных / Структуры и классы
Документация по MQL5: Основы языка / Типы данных / Структуры и классы
  • www.mql5.com
Основы языка / Типы данных / Структуры и классы - Документация по MQL5
 

Да, блин, что-то раньше переменнные типа структуры, будучи неинициализированными, таких ошибок не вызывали.

 
Yedelkin:

Да, блин, что-то раньше переменнные типа структуры, будучи неинициализированными, таких ошибок не вызывали.

А документацию почитать?

С самого начала предупреждали - инициализируйте явно. Просто в какой-то момент стековые переменные попадали в память, инициализированную нулями. Причём это было только в 32-битном терминале. Совершенно случайно. Так же случайно эта память перестала быть инициализированной. Но ведь специальная глава в документации этому вопросу посвящена!

 

А показать, где в документации (а особенно в статьях для начинающих) приведены примеры явной инициализации переменных типа структур при помощи функции ZeroMemory() после их объявления? :)

В том же самом разделе, на который Вы ссылаетесь, указан только способ объявления переменных типа структур без какой-либо их инициализации  с помощью функции ZeroMemory()  при  объявлении. Так что реплика "Но ведь специальная глава в документации этому вопросу посвящена!" верна только в той части, которая не касается затронутой мною темы.

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

 

Кроме ZeroMemory можно использовать запись типа

   SomeStruct str_variable1={0};

которая в документации представлена очень обширно. И описание этому явлению есть

В ссылаемом мною разделе самая первый параграф звучит так:

Любая переменная при определении может быть инициализирована. Если не произведена явная инициализация переменной, то значение, хранящееся в данной переменной, может быть каким угодно. Неявная инициализация не производится.

 

1. Итак, выяснилось, что не удаётся показать, где в документации приведены примеры явной инициализации  переменных типа структур при помощи функции ZeroMemory() после их объявления. Ни в разделе по предложенной ссылке, ни в самом Справочнике нет таких примеров.  Уже хорошо.

2.

stringo:

Кроме ZeroMemory можно использовать запись типа

SomeStruct str_variable1={0};

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

Да, насчёт самой записи верно. Про такую возможность пару недель назад сказал Ренат. А вот насчёт "обширности представления такой записи в документации" - утверждение весьма интересное. Не могли бы Вы привести хотя бы пару ссылок на Справочник в подтверждение такой "обширности"? Напомню, речь идёт об инициализации нулями переменной типа структуры, после объявления такой переменной. Пока что Справочник переполнен вот такими примерами (достаточно в поиске набрать название одной из предопределённых структур):

//+------------------------------------------------------------------+
//|  установить случайным образом отложенный ордер                   |
//+------------------------------------------------------------------+
uint SendRandomPendingOrder(long const magic_number)
  {
//--- готовим запрос
   MqlTradeRequest request;
   request.action=TRADE_ACTION_PENDING;         // установка отложенного ордера
   request.magic=magic_number;                  // ORDER_MAGIC
   request.symbol=_Symbol;                      // инструмент
   request.volume=0.1;                          // объем в 0.1 лот
   request.sl=0;                                // Stop Loss не указан
   request.tp=0;                                // Take Profit не указан   
//--- сформируем тип ордера
   request.type=GetRandomType();                // тип ордера
//---сформируем цену для отложенного ордера
   request.price=GetRandomPrice(request.type);  // цена для открытия
//--- отправим торговый приказ
   MqlTradeResult result;
   OrderSend(request,result);

 

//+------------------------------------------------------------------+
//|  Отправка торгового запроса с обработкой результата              |
//+------------------------------------------------------------------+
bool MyOrderSend(MqlTradeRequest request,MqlTradeResult result)
  {
//--- сбросим код последней ошибки в ноль
   ResetLastError();
//--- отправим запрос
   bool success=OrderSend(request,result);
//+------------------------------------------------------------------+
//|  получить цену случайным образом                                 |
//+------------------------------------------------------------------+
double GetRandomPrice(ENUM_ORDER_TYPE type)
  {
   int t=(int)type;
//--- уровень стопов по символу
   int distance=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
//--- получим данные последнего тика
   MqlTick last_tick;
   SymbolInfoTick(_Symbol,last_tick);

И так далее. Для начинающего такие примеры даже намёка не содержат на то, что переменные типа предопределённых структур надо бы инициализировать перед использованием. Вот так порой документация способствует формированию некорректного стиля программирования. Хорошо хоть, на форуме ошибки помогают исправить.

3.

stringo:

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

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

 Во-вторых, речь ведь не о том, какие значения хранятся в неинициализированной переменной типа структуры, а о том, что с некоторых пор при наличии неинициализированных переменных типа предопределённых структур перестали корректно обрабатываться торговые запросы (в том числе, запросы, составленные по образу и подобию примеров из Справочника). Раз так, значит, Справочник надо уточнять.

 

Любая переменная может быть инициализирована. А может быть не инициализирована. Должна пременная быть инициализирована или не должна, решать программисту, исходя из его алгоритма. Но если программист не проинициализирует локальную переменную, никто за него этого не сделает.

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

"Если писать документацию для идиотов, то только идиоты и будут её читать" (ц) не помню чей

Документацию, конечно же, будем уточнять. Но без фанатизьма.

PS Кстати, в приводимых Вами наших примерах все необходимые поля структуры MqlTradeRequest инициализируются. То есть, явная почленная инициализация. А переменная типа структуры MqlTradeResult не требует инициализации, так как она не является входной, а принимает результат


 
stringo:
 

PS Кстати, в приводимых Вами наших примерах все необходимые поля структуры MqlTradeRequest инициализируются. То есть, явная почленная инициализация.

Если быть более точными в формулировках, то имеем вот что:

1. Значения полям переменной типа структуры  MqlTradeRequest присваиваются не во всех приведённых выше примерах, а только в одном:

uint SendRandomPendingOrder(long const magic_number)
  {
//--- готовим запрос
   MqlTradeRequest request;
   request.action=TRADE_ACTION_PENDING;         // установка отложенного ордера
   request.magic=magic_number;                  // ORDER_MAGIC
   request.symbol=_Symbol;                      // инструмент
   request.volume=0.1;                          // объем в 0.1 лот
   request.sl=0;                                // Stop Loss не указан
   request.tp=0;                                // Take Profit не указан   
//--- сформируем тип ордера

 2. В этом самом примере происходит вот что: сначала  (а) объявляется переменная request типа MqlTradeRequest без какой-либо "инициализации при объявлении", затем (б) отдельным полям этой неинициализированной переменной присваиваются конкретные значения. Вы предлагаете это считать "явной почленной инициализацией", а пример - корректным. Хорошо, пусть будет так. Только отметим, что при подобной инициализации часть полей переменной request так и остались "непроинициализированными".

А теперь смотрим тему о том, что с некоторых пор присваивание значений  лишь отдельным (необходимым)  полям неинициализированной переменной типа  MqlTradeRequest является некорректным. Иными словами, необходимо обнулять всю переменную типа структуры MqlTradeRequest после объявления такой переменной.

Дополнение от 25.01.12. Что касается

stringo:

"Если писать документацию для идиотов, то только идиоты и будут её читать" (ц) не помню чей

Документацию, конечно же, будем уточнять. Но без фанатизьма.

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

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

 

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

"Не всегда переменную надо инициализировать перед первым использованием" действительно нисколько не противоречит предыдущему высказыванию. Поскольку переменные могут выступать не только в качестве r-value, но и l-value. Пример:

a=b+c;

Переменная а (l-value) может содержать что угодно перед её использованием в качестве l-value - неважно, проинициализирована она или нет

Переменные b и c (r-value) должны содержать определённые значения перед их использованием в качестве r-value, то есть должны быть либо проинициализированными, либо предварительно выступить в качестве l-value


Теперь про присвоение значений отдельным (необходимым) полям. Если Вам не нужно устанавливать стоп-лосс и тейк-профит, это не означает, что эти поля не нужны! Как программист, который должен владеть предметной областью, Вы должны понимать, что эти поля нужны всегда при выставлении приказа. Даже в примере, который Вы же и процитировали

   request.sl=0;                                // Stop Loss не указан
   request.tp=0;                                // Take Profit не указан

стоят явные комментарии к нулевым значениям


"Без фанатизма" означает принцип необходимой достаточности. Если перегрузить документацию ненужными подробностями, её будет трудно читать. И давайте не уподобляться североамериканским потребителям, которые не знают, что домашних животных нельзя сушить в микроволновке, потому что об этом ничего не сказано в инструкции.

Да, учебника по MQL5 ещё нет. Однако, даже наличие десятка таких учебников не гарантирует, что некто не найдёт там необходимой в данный момент информации в том виде, в котором этот некто хотел бы эту информацию видеть.

 

Так, чтоб не потерять нить обсуждения.

1. Выяснилось, что отсылка к справочнику и к специальной главе в нём не привела ни к нахождению способа, позволившего 1Serg'у устранить ошибку (т.е. через использование ZeroMemory), ни к нахождению записи типа "SomeStruct str_variable1={0};", которая презентовалась как широко представленная в документации. Тем не менее, обоснованность такой отсылки к справочнику сомнений не вызвала, поскольку "на всех - примеров не напасёшься" (ну или как-то так).

2. Попытка показать, что имеющиеся в документации примеры по затронутой теме являются некорректными, привела к вычленению из всех некорректных примеров одного, в котором обязательным полям неинициализированной переменной типа MqlTradeRequest присваивались определённые значения. Вы посчитали этот пример корректным, а предложенную ссылку  смотреть не стали.

3. Вместо просмотра ссылки было сказано:

stringo:

Теперь про присвоение значений отдельным (необходимым) полям. Если Вам не нужно устанавливать стоп-лосс и тейк-профит, это не означает, что эти поля не нужны! Как программист, который должен владеть предметной областью, Вы должны понимать, что эти поля нужны всегда при выставлении приказа. Даже в примере, который Вы же и процитировали

   request.sl=0;                                // Stop Loss не указан
   request.tp=0;                                // Take Profit не указан

стоят явные комментарии к нулевым значениям 

Отсюда и продолжим. А зачем Вы в термин "необходимые поля" из  моей фразы ("...с некоторых пор присваивание значений  лишь отдельным (необходимым)  полям неинициализированной переменной типа  MqlTradeRequest является некорректным") вкладываете смысл, отличный от смысла, придаваемого Справочником? :) Поясняю: под "необходимыми полями" имеются в виду обязательные/требуемые_к_заполнению поля, о которых идёт речь в Справочнике MQL5 / Стандартные константы, перечисления и структуры / Структуры данных / Структура торгового запроса. Каждому варианту торгового запроса - свои обязательные (необходимые) к заполнению поля.

Поэтому перефразирую ту фразу: с некоторых пор присваивание значений  лишь отдельным (всем обязательным с точки зрения Справочника)  полям неинициализированной переменной типа  MqlTradeRequest является некорректным.

Цитирую:

Automated-Trading:

... Проблема была в структуре mrequest, предварительно ее нужно обнулять при помощи функции ZeroMemory. Перед строками с "mrequest.action=TRADE_ACTION_DEAL;" (стр. 199 и 245) нужно добавить "ZeroMemory(mrequest);"

Automated-Trading:
Перед отправкой запроса все поля структуры должны быть инициализированы (в данном случае это производится при помощи функции ZeroMemory, хотя можно сделать это поэлементно), инициализацию надо проводить после объявления структуры.

Таким образом, приходим к тому, что Вы настаиваете на корректности примера, в котором заполнены только обязательные поля неинициализированной переменной типа  MqlTradeRequest, а Ваш коллега фактически пишет о некорректности использования неинициализированной переменной типа  MqlTradeRequest, у которой заполнены только обязательные поля.

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