Fehler, Irrtümer, Fragen - Seite 2591

 
Koldun Zloy:

Was passiert, wenn die kopierte Zeichenfolge größer oder kleiner ist als die zugewiesene Puffergröße?

Wenn er kleiner ist, ist das in Ordnung. In der Regel ist der String-Puffer immer etwas größer als der String selbst (aber das ist keine Tatsache!)

Wenn Sie aber mehr als das schreiben, ist es fast garantiert, dass das Terminal abstürzt.
Und der Absturz wird höchstwahrscheinlich nicht sofort passieren, sondern erst bei der nächsten Arbeit mit dynamischem Speicher (Neuzuweisung von Arrays oder Stringpuffern) oder beim Herunterfahren, wenn der verwendete MQL-Programmspeicher an das System zurückgegeben wird

 
Ilyas:

1. in MQL nur Unicode, deshalb ist die Zeichengröße 2 Bytes

2. String ist eine Struktur (4 Byte Puffergröße und 8 Byte Zeigergröße)


Das Kopieren in einen String sollte

Wenn es nicht funktioniert, muss der Fehler an anderer Stelle gefunden werden

Ja, die einfachste Funktion

wcscpy(out, data);

und verursacht ein Problem. Die Zeile wird gleichmäßig kopiert, aber es gibt große Sprünge. Das heißt, es gibt eine Verzögerung beim Kopieren.
Deshalb wurden andere Funktionen ausprobiert, die bei korrekter Anwendung ebenfalls das Problem verursachen.
Alle Arten von mutex, recursive_mutex, lock_guard lösen das Problem des Überspringens nicht.

Deshalb weiß ich nicht mehr, was ich denken soll, der String aus der Steckdose kommt richtig,
Der erhaltene String-Typ wchar_t* bedeutet automatisch, dass er Unicode-kodiert ist und jedes Zeichen im String 2 Bytes entspricht (getestet).
Aber ich verstehe nicht, dass der wchar_t*-Zeiger in einen String mit acht und zwölf Bytes kopiert wird.
Vielleicht ist es der Bitmodus des Betriebssystems, der dies irgendwie beeinflusst? Alles wird auf 64-Bit-Versionen, Windows und Linux geprüft.

 

Ich verstehe nicht, was sind die Lücken? Leere Zeilen?

Schreiben Sie von allen Threads in dieselbe MQL-Zeile oder in verschiedene?

Wann in MQL-Code entscheiden Sie, dass es Daten in der Zeichenfolge und es kann verarbeitet/ausgegeben werden?


Wenn alles in einer Zeile steht, was falsch ist, dann brauchen Sie einen kritischen Abschnitt auf der DLL-Seite, der von MQL und dem Zeilenwechselzähler zugänglich ist


Pseudocode von 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);
     }
  }


Dies ist ein Beispielschema und es werden Zeilen von der MMS-Seite übersprungen (nicht alle Zeilen gelangen zur MMS, einige von ihnen werden überschrieben)

 
Ilyas:

Ich verstehe nicht, was sind die Lücken? Leere Zeilen?

Schreiben Sie von allen Threads in dieselbe MQL-Zeile oder in verschiedene?

Wann in MQL-Code entscheiden Sie, dass es Daten in der Zeichenfolge und es kann verarbeitet/ausgegeben werden?


Wenn alles in einer Zeile steht, was falsch ist, dann brauchen Sie einen kritischen Abschnitt auf der DLL-Seite, der von MQL und dem Zeilenwechselzähler zugänglich ist


Pseudocode von MQL

DLL


Dies ist ein Beispielschema und es werden Zeilen von der MQL-Seite übersprungen (nicht alle Zeilen werden an MQL gelangen, einige werden überschrieben)

Ja, leere Zeilen, wie Sie auf dem Screenshot sehen können.
Ja, von allen Gewinden zu einer MMS-Linie. Da die Erstellung von Variablen für die Zeichenkette im laufenden Betrieb ebenfalls problematisch ist.
Wenn wir vorher nicht wissen, wie viele Quellen beteiligt sein werden, woher die Strings kommen, also dynamisch.
Ich habe auch über kritische Abschnitte nachgedacht und dachte auch, dass MQL eine Möglichkeit blockieren sollte, sie zu lesen. Danke für das Beispiel, ich werde es mir überlegen.
Aber es stellt sich heraus, dass Sie immer noch empfehlen, um jede Zeichenfolge Quelle in einer eigenen separaten Variable zu erhalten? Und nicht in einer Variablen von MQL.
Es ist einfach bequemer, mit den von allen Threads empfangenen Daten in einer String-Variablen zu arbeiten.
Ich dachte, dass, wenn es eine Schreibsperre auf der DLL-Seite ist, in MQL Lesen nicht eine Sperre erfordert, d.h. es ist, als ob MQL eine solche Kopieren Implementierung berücksichtigt.
Aber selbst wenn ich eine Zeichenkette aus einem Thread erhalte, bekomme ich immer noch Aussetzer!
Wenn ich andere Kopierfunktionen mit korrekten Parametern verwende, erhalte ich keine Auslassungen, unabhängig davon, ob es sich um einen oder mehrere Threads handelt, aber ich erhalte immer noch eine ungerade Zeichenfolge.
Wenn Sie die falschen Parameter verwenden, ist die Zeichenkette zwar gleichmäßig, aber sie wird undicht.

Dateien:
458.png  71 kb
 
Ilyas:

Weniger ist in Ordnung, denn normalerweise ist der String-Puffer immer etwas größer als der String selbst (aber das ist keine Tatsache!)

Wenn Sie jedoch mehr schreiben, ist ein Absturz des Terminals fast sicher.
Und ein Absturz wird höchstwahrscheinlich nicht sofort erfolgen, sondern erst bei der nächsten dynamischen Speicheroperation (Umverteilung von Arrays oder Stringpuffern) oder beim Herunterfahren, wenn der benutzte Speicher von MQL-Programmen an das System zurückgegeben wird

Warum raten Sie dann einem Neueinsteiger, die Funktionwcscpy zu verwenden?

Es gibt sicherere Funktionen: wcscpy_s, wmemcpy_s.

 

Bitte erklären Sie, warum im OnCalculate-Handler die Zeit jedes neu gebildeten Balkens time[0] vor der Tick-Zeit liegt, die wir mit der Funktion SymbolInfoTick anfordern? DieFunktion SymbolInfoTick sollte immer den letzten bekannten Tick zurückgeben.

Ich füge einen Indikator bei, der dieses Problem im Testgerät im Schweißmodus reproduziert.

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

An jeder Taktgrenze gibt es dieses Problem.

PS. Und laut der Dokumentation, dass OnCalculate für alle Ticks ohne Auslassung aufgerufen wird, sollte das Tick-Volumen immer mit dem Tick-Zähler übereinstimmen, aber das ist nicht immer der Fall.
Dateien:
fake.mq5  2 kb
 
Stanislav Korotky:

Bitte erklären Sie, warum im OnCalculate-Handler die Zeit jedes neu gebildeten Balkens time[0] vor der Tick-Zeit liegt, die wir mit der Funktion SymbolInfoTick anfordern? Die Funktion SymbolInfoTick sollte immer den letzten bekannten Tick zurückgeben.

Ich füge einen Indikator bei, der dieses Problem im Testgerät im Schweißmodus reproduziert.

An jeder Taktgrenze gibt es dieses Problem.

PS. Auch dieser Indikator zeigt ein weiteres Problem: Es gibt eine Tick-Zählung, und nach der Aussage in der Dokumentation zu urteilen, dass OnCalculate für alle Ticks aufgerufen wird, ohne dass sie fehlen, sollte das Tick-Volumen immer mit dem Tick-Zähler übereinstimmen, aber das ist nicht immer der Fall.

Bitte geben Sie mir die Build-Nummer an.

 
Slava:

Bitte geben Sie mir die Build-Nummer

2093

 
Stanislav Korotky:

2093

Das von Ihnen beschriebene Problem wurde in Build 2155 behoben.

 

Die hervorgehobene Konstante SYMBOL_CHART_MODE_OLD wurde im Editor gefunden.

Natürlich ist es nicht in ENUM_SYMBOL_CHART_MODE.

Was ist das?

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