Errores, fallos, preguntas - página 2591

 
Koldun Zloy:

¿Qué ocurre si la cadena copiada es mayor o menor que el tamaño del buffer asignado?

Si es más pequeño no pasa nada, normalmente el buffer de la cadena es siempre ligeramente mayor que la propia cadena (¡pero eso no es un hecho!)

Pero si escribes más que eso, está casi garantizado que el terminal se bloqueará.
Y lo más probable es que el fallo no se produzca inmediatamente, sino sólo en el siguiente trabajo con memoria dinámica (reasignación de arrays o buffers de cadenas) o en el apagado, cuando la memoria del programa MQL utilizado se devuelve al sistema

 
Ilyas:

1. en MQL sólo Unicode, por eso el tamaño de los caracteres es de 2 bytes

2. la cadena es una estructura (4 bytes de tamaño de búfer y 8 bytes de tamaño de puntero)


Copiar a la cadena debe ser

Si no funciona, el error debe encontrarse en otra parte

Sí, la función más sencilla

wcscpy(out, data);

y causa un problema. La línea se copia uniformemente, pero hay grandes saltos. Es decir, hay un retraso en la copia.
Por eso se han probado otras funciones, que también causan el problema si se usan correctamente.
Todo tipo de mutex, recursive_mutex, lock_guard no resuelven el problema de la omisión.

Debido a esto ya no sé qué pensar, la cadena del enchufe viene correctamente,
recibir el tipo de cadena wchar_t* significa automáticamente que está codificada en Unicode y que cada carácter de la cadena equivale a 2 bytes (probados).
Pero no entiendo que el puntero wchar_t* se copie a la cadena con ocho bytes y doce bytes.
¿Tal vez sea el modo de bits del SO el que influye de alguna manera? Todo está comprobado en las versiones de 64 bits, Windows y Linux.

 

No entiendo, ¿qué son los huecos? ¿Líneas en blanco?

¿Escribes desde todos los hilos a la misma línea MQL o a diferentes?

¿En qué momento del código MQL se decide que hay datos en la cadena y que pueden ser procesados/salidos?


Si todo está en una línea, lo cual es erróneo, entonces se necesita una sección crítica en el lado de la DLL, que es accesible desde MQL y el contador de cambios de línea


Pseudocódigo de 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);
     }
  }


Este es un esquema de ejemplo y habrá saltos de líneas desde el lado de MQL (no todas las líneas llegarán a MQL, algunas de ellas serán sobrescritas)

 
Ilyas:

No entiendo, ¿qué son los huecos? ¿Líneas en blanco?

¿Escribes desde todos los hilos a la misma línea MQL o a diferentes?

¿En qué momento del código MQL se decide que hay datos en la cadena y que pueden ser procesados/salidos?


Si todo está en una línea, lo cual es erróneo, entonces se necesita una sección crítica en el lado de la DLL, que es accesible desde MQL y el contador de cambios de línea


Pseudocódigo de MQL

DLL


Este es un esquema de ejemplo y habrá saltos de líneas desde el lado de MQL (no todas las líneas llegarán a MQL, algunas de ellas serán sobrescritas)

Sí líneas vacías, se puede ver en la captura de pantalla.
Sí de todos los hilos a una línea MQL. Ya que crear variables para la cadena sobre la marcha también es problemático.
Si no sabemos de antemano cuántas fuentes van a intervenir, de dónde proceden las cadenas, es decir, de forma dinámica.
También estaba pensando en las secciones críticas y también pensé que MQL debería bloquear alguna manera de leer. Gracias por el ejemplo, lo pensaré.
Pero resulta que todavía recomienda obtener cada fuente de cadena en su propia variable separada? Y no en una variable de MQL.
Es que es más cómodo trabajar con los datos recibidos de todos los hilos desde una sola variable de cadena.
Pensé que si hay un bloqueo de escritura en el lado de la dll, en MQL la lectura no requiere un bloqueo, es decir, es como si MQL tiene en cuenta dicha implementación de copia.
Pero incluso si obtengo una cadena de un hilo, ¡sigo teniendo saltos!
Si utilizo otras funciones de copia con parámetros correctos, no obtendré saltos, no importa si es uno o varios hilos, pero seguiré obteniendo una cadena de caracteres desigual.
Si usas parámetros incorrectos, la cadena es pareja, pero empieza a filtrarse.

Archivos adjuntos:
458.png  71 kb
 
Ilyas:

Si es menos está bien, normalmente el buffer de la cadena es siempre ligeramente mayor que la propia cadena (¡pero eso no es un hecho!)

Pero si escribes más, es casi seguro que se produzca una caída del terminal.
Y lo más probable es que el fallo no se produzca inmediatamente, sino sólo en la siguiente operación de memoria dinámica (redistribución de arrays o buffers de cadenas) o en el apagado, cuando la memoria utilizada de los programas MQL se devuelve al sistema

Entonces, ¿por qué aconsejas a un novato que utilice la funciónwcscpy?

Hay funciones más seguras: wcscpy_s, wmemcpy_s.

 

Por favor, explique por qué en el manejador OnCalculate el tiempo de cada barra recién formada time[0] se adelanta al tiempo del tick que solicitamos mediante la función SymbolInfoTick. Lafunción SymbolInfoTick debe devolver siempre el último tick conocido.

Adjunto un indicador que reproduce este problema en el probador en modo sudor.

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

En cada límite de la barra existe este problema.

PS. Y según la documentación, que OnCalculate es llamado para todos los ticks sin omisión, el volumen de ticks debería coincidir siempre con el contador de ticks, pero no siempre es así.
Archivos adjuntos:
fake.mq5  2 kb
 
Stanislav Korotky:

Por favor, explique por qué en el manejador OnCalculate el tiempo de cada barra recién formada time[0] está por delante del tiempo de tick que estamos solicitando con la función SymbolInfoTick? La función SymbolInfoTick debe devolver siempre el último tick conocido.

Adjunto un indicador que reproduce este problema en el probador en modo sudor.

En cada límite de la barra existe este problema.

PS. También este indicador demuestra otro problema: hay conteo de ticks, y a juzgar por la declaración en la documentación de que OnCalculate es llamado para todos los ticks sin faltar, el volumen de ticks debería coincidir siempre con el contador de ticks, pero esto no es siempre el caso.

Por favor, dame el número de construcción.

 
Slava:

Por favor, indíqueme el número de fabricación

2093

 
Stanislav Korotky:

2093

El problema que describes se ha solucionado en la versión 2155

 

Encontré la constante resaltada SYMBOL_CHART_MODE_OLD en el editor.

Por supuesto, no está en ENUM_SYMBOL_CHART_MODE.

¿Qué es?

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