Ошибки, баги, вопросы - страница 2591

 
Koldun Zloy:

А что будет, если размер копируемой строки будет больше или меньше, чем размер выделенного буфера?

Если меньше ничего страшного, как правило, буфер строки всегда немного больше чем сама строка (но это не факт!)

А вот в случае, если записать больше, то практически наверняка гарантировано аварийное завершение терминала.
И аварийное завершение скорее всего произойдёт не сразу, а только при следующей работе с динамической памятью (перераспределение массивов или буферов строк) или на завершении работы, когда использованная память MQL программ возвращается в систему

 
Ilyas:

1. в MQL только юникод, поэтому и размер символа 2 байта

2. cтрока это структура (4 байта размер буфера и 8 байт указатель)


Копирование в строку должно быть таким

Если это не работает, то ошибку надо искать в другом месте

Да, самая простая функция 

wcscpy(out, data);

и вызывает проблему. Строка копируется ровная, но идут большие пропуски. То есть задержка в копировании.
По этому и были испробованы другие функции, которые так же вызывают проблему, если использовать их правильно.
Всякие mutex, recursive_mutex, lock_guard не решают проблему пропусков.

По этому уже не знаю куда думать, повторю строка из сокета приходит корректная,
тип получаемой строки wchar_t* автоматом подразумевает что она в кодировке Unicode, и в строке каждый символ равен 2 байтам (проверено).
Но вот как то до меня не доходит, что будет корректное копирование указателя wchar_t* восемь байт, в string двенадцать байт.
Может разрядность OS ещё как то влияет? Всё проверяется на 64 битных версиях, Windows и Linux.

 

Не понятно, что за пропуски ?  Пустые строки ?

Вы из всех потоков в одну MQL строку пишете или в разные ?

Когда в MQL коде решаете, что данные в строке есть и их можно обработать/вывести ?


Если всё в одну строку, что неправильно, то нужна критическая секция на стороне DLL, к которой есть доступ из MQL и счётчик изменений строки


Псевдо код из MQL

#import ...
   bool LockValueIfChanged();
   void UnlockValue();
#import


while(!_IsStopped())
  {
   if(LockValueIfChanged())
     {
      Print( Value );
      UnlockValue();
     }
  }

DLL

uint64_t last_mql_counter=0;
uint64_t counter=0;

bool LockValueIfChanged()
  {
   Lock(cs);

   if(last_mql_counter!=counter)
    {
     last_mql_counter=counter;
     return(true);
    }

   Unlock(cs);
   return(false);
  }

void UnlockValue()
  {
   Unlock(cs);
  }

Thread()
  {
   while( running )
     {
      Lock(cs);

      Value = ...

      counter++;

      Unlock(cs);
     }
  }


Это примерная схема и по ней будут пропуски строк со стороны MQL (не все строки получите в MQL, часть из них будет перезаписана)

 
Ilyas:

Не понятно, что за пропуски ?  Пустые строки ?

Вы из всех потоков в одну MQL строку пишете или в разные ?

Когда в MQL коде решаете, что данные в строке есть и их можно обработать/вывести ?


Если всё в одну строку, что неправильно, то нужна критическая секция на стороне DLL, к которой есть доступ из MQL и счётчик изменений строки


Псевдо код из MQL

DLL


Это примерная схема и по ней будут пропуски строк со стороны MQL (не все строки получите в MQL, часть из них будет перезаписана)

Да пустые строки, на скрине это видно.
Да из всех потоков в одну строку MQL. Так как создание переменных для строки на лету, это тоже проблемное занятие.
Если заранее не известно сколько будет задействовано источников от куда приходят строки , то есть динамически.
За критические секции тоже была мысль, тоже думал что нужно со стороны MQL как то блокировать чтение. Спасибо за пример, буду обдумывать.
Но получается вы всё же рекомендуете каждый источник строки, получать в свою отдельную переменную? А не в одну переменную строки MQL.
Просто из одной переменной строки, удобнее работать с полученными данными из всех потоков.
Я думал что если есть блокировка записи на стороне dll, то в MQL чтение не требует блокировки, то есть в MQL как бы учтена такая реализация копирования. 
Но даже если получать строку из одного потока, то всё равно идут пропуски!
И если использовать другие функции копирования, с правильными параметрами, то пропусков нет, хоть один, хоть несколько потоков, но получается не ровная строка по символам.
Используешь не правильные параметры, строка получается ровная, но начинает течь.

Файлы:
458.png  71 kb
 
Ilyas:

Если меньше ничего страшного, как правило, буфер строки всегда немного больше чем сама строка (но это не факт!)

А вот в случае, если записать больше, то практически наверняка гарантировано аварийное завершение терминала.
И аварийное завершение скорее всего произойдёт не сразу, а только при следующей работе с динамической памятью (перераспределение массивов или буферов строк) или на завершении работы, когда использованная память MQL программ возвращается в систему

Тогда почему Вы советуете новичку использовать функцию wcscpy?

Есть же более безопасные функции: wcscpy_s, wmemcpy_s.

 

Объясните пожалуйста, почему в обработчике OnCalculate время каждого вновь образованного бара time[0] опережает время тика, которое мы запрашиваем с помощью функции SymbolInfoTick? По идее, если уже есть бар time[0], то должен существовать тик, его породивший, а функция SymbolInfoTick яко-бы должна всегда возвращать последний известный тик.

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

2019.10.12 16:51:53.667 2019.01.02 06:00:00   Time 2019.01.02 06:00:00 = 1546408800000 is ahead of tick:  1546297199572
2019.10.12 16:51:53.753 2019.01.02 06:01:00   Time 2019.01.02 06:01:00 = 1546408860000 is ahead of tick:  1546408830000
2019.10.12 16:51:54.315 2019.01.02 06:02:00   Time 2019.01.02 06:02:00 = 1546408920000 is ahead of tick:  1546408919000
2019.10.12 16:51:54.617 2019.01.02 06:03:00   Time 2019.01.02 06:03:00 = 1546408980000 is ahead of tick:  1546408979000

На каждой границе баров есть такая проблема.

PS. Также в данном индикаторе демонстрируется другая проблема: там ведется подсчет тиков, и судя по утверждению документации, что OnCalculate вызывается для всех тиков без пропуска, тиковый объем должен всегда совпадать со счетчиком тиков, однако это не всегда так.
Файлы:
fake.mq5  2 kb
 
Stanislav Korotky:

Объясните пожалуйста, почему в обработчике OnCalculate время каждого вновь образованного бара time[0] опережает время тика, которое мы запрашиваем с помощью функции SymbolInfoTick? По идее, если уже есть бар time[0], то должен существовать тик, его породивший, а функция SymbolInfoTick яко-бы должна всегда возвращать последний известный тик.

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

На каждой границе баров есть такая проблема.

PS. Также в данном индикаторе демонстрируется другая проблема: там ведется подсчет тиков, и судя по утверждению документации, что OnCalculate вызывается для всех тиков без пропуска, тиковый объем должен всегда совпадать со счетчиком тиков, однако это не всегда так.

Номер билда сообщите пожалуйста

 
Slava:

Номер билда сообщите пожалуйста

2093

 
Stanislav Korotky:

2093

Описанная Вами проблема была исправлена в билде 2155

 

Обнаружил в редакторе подсвечиваемую константу SYMBOL_CHART_MODE_OLD.

В ENUM_SYMBOL_CHART_MODE её, естественно, нету.

Что это?

Документация по MQL5: Константы, перечисления и структуры / Состояние окружения / Информация об инструменте
Документация по MQL5: Константы, перечисления и структуры / Состояние окружения / Информация об инструменте
  • www.mql5.com
Для получения текущей рыночной информации служат функции SymbolInfoInteger(), SymbolInfoDouble() и SymbolInfoString(). В качестве второго параметра этих функций допустимо передавать один из идентификаторов из перечислений ENUM_SYMBOL_INFO_INTEGER, ENUM_SYMBOL_INFO_DOUBLE и ENUM_SYMBOL_INFO_STRING соответственно. Некоторые символы (как...
Причина обращения: