Errori, bug, domande - pagina 2591

 
Koldun Zloy:

Cosa succede se la stringa copiata è più grande o più piccola della dimensione del buffer allocato?

Se è più piccolo va bene, di solito il buffer delle stringhe è sempre leggermente più grande della stringa stessa (ma questo non è un fatto!)

Ma se si scrive di più, è quasi garantito che il terminale si blocca.
E il crash molto probabilmente non avverrà immediatamente, ma solo al prossimo lavoro con la memoria dinamica (riallocazione di array o buffer di stringhe) o allo spegnimento, quando la memoria usata del programma MQL viene restituita al sistema

 
Ilyas:

1. in MQL solo Unicode, ecco perché la dimensione del carattere è di 2 byte

2. la stringa è una struttura (4 byte di dimensione del buffer e 8 byte di dimensione del puntatore)


La copia su stringa dovrebbe essere

Se non funziona, l'errore dovrebbe essere trovato altrove

Sì, la funzione più semplice

wcscpy(out, data);

e causa un problema. La linea è copiata uniformemente, ma ci sono grandi salti. Cioè, c'è un ritardo nella copia.
Per questo sono state provate altre funzioni, che causano anche il problema se usate correttamente.
Tutti i tipi di mutex, recursive_mutex, lock_guard non risolvono il problema del salto.

A causa di questo non so più cosa pensare, la stringa dalla presa arriva correttamente,
ricevuto il tipo di stringa wchar_t* significa automaticamente che è codificato in Unicode, e ogni carattere nella stringa è uguale a 2 byte (testato).
Ma non capisco che il puntatore wchar_t* sarà copiato nella stringa con otto byte e dodici byte.
Forse le dimensioni delle periferiche bit del sistema operativo hanno qualche altra influenza? Tutto è controllato sulle versioni a 64 bit, Windows e Linux.

 

Non capisco, cosa sono i vuoti, le linee vuote?

Scrivete da tutti i thread sulla stessa linea MQL o su altre?

Quando nel codice MQL si decide che ci sono dati nella stringa e che possono essere elaborati/output?


Se tutto è in una linea, il che è sbagliato, allora avete bisogno di una sezione critica sul lato DLL, che è accessibile da MQL e dal contatore di cambio linea


Codice pseudo da 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);
     }
  }


Questo è uno schema di esempio e ci sarà un salto di linee dal lato MQL (non tutte le linee arriveranno al MQL, alcune di esse saranno sovrascritte)

 
Ilyas:

Non capisco, cosa sono i vuoti, le linee vuote?

Scrivete da tutti i thread sulla stessa linea MQL o su altre?

Quando nel codice MQL si decide che ci sono dati nella stringa e che possono essere elaborati/output?


Se tutto è in una linea, il che è sbagliato, allora avete bisogno di una sezione critica sul lato DLL, che è accessibile da MQL e dal contatore di cambio linea


Codice pseudo da MQL

DLL


Questo è uno schema di esempio e ci sarà un salto di linee dal lato MQL (non tutte le linee arriveranno al MQL, alcune di esse saranno sovrascritte)

Sì, linee vuote, lo puoi vedere nello screenshot.
Sì da tutte le filettature a una linea MQL. Poiché anche la creazione di variabili per la stringa al volo è problematica.
Se non sappiamo in anticipo quante fonti saranno coinvolte da dove provengono le stringhe, in altre parole, dinamicamente.
Stavo anche pensando alle sezioni critiche e ho anche pensato che MQL dovrebbe bloccare qualche modo per leggerle. Grazie per l'esempio, ci penserò.
Ma si scopre che si consiglia ancora di ottenere ogni fonte di stringa in una propria variabile separata? E non in una variabile di MQL.
È solo che è più conveniente lavorare con i dati ricevuti da tutti i thread da una variabile stringa.
Ho pensato che se c'è un blocco di scrittura sul lato dll, in MQL la lettura non richiede un blocco, cioè è come se MQL tenesse conto di una tale implementazione della copia.
Ma anche se ottengo una stringa da un filo, ottengo comunque dei salti!
Se uso altre funzioni di copiatura con parametri corretti, non otterrò salti, non importa se si tratta di uno o più fili, ma otterrò comunque una stringa di caratteri irregolare.
Se si usano parametri sbagliati, la stringa è pari, ma inizia a perdere.

File:
458.png  71 kb
 
Ilyas:

Se meno va bene, di solito il buffer delle stringhe è sempre leggermente più grande della stringa stessa (ma questo non è un fatto!)

Ma se si scrive di più, un crash del terminale è quasi certamente garantito.
E il crash molto probabilmente non avverrà immediatamente, ma solo alla prossima operazione di memoria dinamica (ridistribuzione di array o buffer di stringhe) o allo spegnimento, quando la memoria usata dei programmi MQL viene restituita al sistema

Allora perché consigliate a un nuovo arrivato di usare la funzionewcscpy?

Ci sono funzioni più sicure: wcscpy_s, wmemcpy_s.

 

Per favore, spiegate perché nel gestore OnCalculate il tempo di ogni barra appena formata time[0] è più avanti del tempo di tick che richiediamo usando la funzione SymbolInfoTick? Lafunzione SymbolInfoTick dovrebbe sempre restituire l'ultimo tick conosciuto.

Allego un indicatore che riproduce questo problema nel tester in modalità sudore.

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

Ad ogni limite della barra c'è questo problema.

PS. E secondo la documentazione, che OnCalculate è chiamato per tutti i tick senza omissione, il volume di tick dovrebbe sempre coincidere con il contatore di tick, ma non è sempre vero.
File:
fake.mq5  2 kb
 
Stanislav Korotky:

Per favore, spiega perché nel gestore OnCalculate il tempo di ogni barra appena formata time[0] è più avanti del tempo di tick che stiamo richiedendo con la funzione SymbolInfoTick? La funzione SymbolInfoTick dovrebbe sempre restituire l'ultimo tick conosciuto.

Allego un indicatore che riproduce questo problema nel tester in modalità sudore.

Su ogni limite della barra c'è questo problema.

PS. Anche questo indicatore dimostra un altro problema: c'è il conteggio dei tick, e a giudicare dalla dichiarazione nella documentazione che OnCalculate viene chiamato per tutti i tick senza mancare, il volume dei tick dovrebbe sempre coincidere con il contatore dei tick, ma questo non è sempre il caso.

Per favore, datemi il numero di costruzione.

 
Slava:

Per favore, datemi il numero di costruzione

2093

 
Stanislav Korotky:

2093

Il problema che hai descritto è stato risolto nella build 2155

 

Trovato la costante evidenziata SYMBOL_CHART_MODE_OLD nell'editor.

Naturalmente non è in ENUM_SYMBOL_CHART_MODE.

Che cos'è?

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