Hilfe bei OOP - Seite 2

 
Ihor Herasko #:
Wenn Sie sich plötzlich mit Renate streiten wollen, herzlich willkommen.

äh, etwa so:

Ihor Herasko #:

Noch eine Sache. Objektarrays werden am besten über einen Zeiger erstellt. Andernfalls erhalten Sie ein Array im Stapelspeicher, das sehr klein ist:

hat nichts mit dem zu tun, was Renat sagt, und mit den oben genannten Beispielen.
 
Ihor Herasko #:

Wenn Sie das Beispiel ein wenig abändern, indem Sie die Deklaration auf lokaler Ebene vornehmen und eine nicht so schreckliche Zahl einsetzen, sagt Ihnen der Compiler direkt, wo das Problem liegt:

Wenn Sie sich mit Renate streiten wollen, können Sie das gerne tun.

In Ihrem Beispiel:

Test *pClassTest[];

wird außerhalb der Funktion als globale Variable definiert. Was ist also der Stapel hier? Es ist ein Haufen.

 
Vasiliy Sokolov #:

In Ihrem Beispiel:

wird außerhalb der Funktion als globale Variable definiert. Was ist also der Stapel hier? Es ist ein Haufen.

Erstaunlich! Vasily, Sie haben sich auf einen Streit eingelassen, ohne zu verstehen, worüber Sie streiten, und ohne sich zu bemühen, zu verstehen, worum es in dem Streit geht?

Igor argumentiert beide Male im Heap, und diese Codezeile stammt aus dem zweiten ("richtigen") Beispiel, das sich kompilieren lässt, im Gegensatz zum ersten, das sich nicht kompilieren lässt (und keinen Zeiger enthält).

 
Ihor Herasko #:

Wenn Sie das Beispiel ein wenig abändern, indem Sie die Deklaration auf lokaler Ebene vornehmen und eine nicht so schreckliche Zahl einsetzen, sagt Ihnen der Compiler direkt, wo das Problem liegt:

Wenn Sie sich plötzlich mit Renate streiten wollen, können Sie das gerne tun.

Zum Thema "nicht schrecklich". Wie sagt man? Der Stack ist standardmäßig 1 MB groß, und Sie weisen ihm ARRAY_SIZE*sizeof(Test) zu, was natürlich größer ist.

 
Ihor Herasko #:

Das ist kein Problem, geschweige denn ein potenzielles Problem. Das liegt nur an den Eigenheiten der Speicherverwaltung in MT. Hier ist ein statisches Array:

Und hier ist ein dynamisches Array:

In diesem Fall wird alles kompiliert und funktioniert.

Weiter geht's.

Im ersten Fall wird der Speicher zur Kompilierzeit zugewiesen. Das heißt, das Segment .data des Programms sollte diese ARRAY_SIZE*sizeof(Test) enthalten. Was war ARRAY_SIZE dort?)) Wenn ich mich nicht irre, kommt die .ex5-Datei unter 2 TB heraus))))

Im zweiten Fall wird die Zuweisung in den Stapel ARRAY_SIZE*sizeof(Test*) bytes, d. h. 480 GB, gelegt,

 

double x[268435448]; im allgemeinen Teil kompiliert.

268435449 lässt sich nicht mehr kompilieren.

Und268435449 kompiliert in OnStart() des Skripts, und es kompiliert in den allgemeinen Abschnitt verlassen diese riesige Array x.

268435448*8=2.147.483.584 sind zwei Gigabyte.

***

Und hier ist der Grenzwert in der Funktion: double x[268435456];

 

Siehe Referenz über Stack:

Gibt die Stack-Größe für MQL5-Programme an. Bei rekursiven Funktionsaufrufen ist eine ausreichende Stack-Größe erforderlich.

Wenn ein Skript oder ein Expert Advisor auf einem Chart gestartet wird, werden mindestens 8 Mb Stack zugewiesen, für Indikatoren funktioniert die Eigenschaft nicht - der Stack ist immer auf 1 Mb festgelegt.

Wenn das Programm im Testprogramm gestartet wird, wird immer ein Stack von 16 MB zugewiesen.


Wir sollten davon ausgehen, dass der Stack nur für rekursive Funktionsaufrufe verwendet wird. Daher bleibt der Stack bei rekursiven Aufrufen unabhängig von der Größe der statischen Arrays unverändert.

 
Dmitry Fedoseev #:

Erstaunlich! Vasiliy, haben Sie sich auf einen Streit eingelassen, ohne zu verstehen, worüber Sie streiten, und ohne sich zu bemühen, zu verstehen, worum es in dem Streit geht?

Igor argumentiert im Heap, und diese Codezeile stammt aus dem zweiten ("richtigen") Beispiel, das sich kompilieren lässt, im Gegensatz zum ersten Beispiel, das sich nicht kompilieren lässt (und das keinen Zeiger enthält).

Gut. Das verstehe ich nicht. Verstehen Sie das? Verstehen Sie das genau? Ganz genau?

Das Argument läuft auf die folgende Aussage hinaus:

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Hilfe bei OOP

Ihor Herasko, 2021.09.19 21:00

Und noch eine Sache. Es ist besser, Arrays von Objekten mit Hilfe eines Zeigers zu erstellen. Andernfalls erhalten Sie ein Array im Stapelspeicher, das sehr klein ist:

Strategy2 *pZ[]; 

Diese Aussage ist falsch. Arrays werden nicht auf dem Stack zugewiesen. Weder durch Zeiger noch statisch. Dies ist leicht zu überprüfen.

Der zweite Punkt: Das Beispiel verwendet Zeiger, die dort aber nicht benötigt werden. Hier ist das entsprechende Beispiel ohne die Bareplate:

#define               ARRAY_SIZE           int(60000000)
class Test
{
public:
   int               nA;
   double            fB;
   datetime          dtC;

                     Test(void)
                       : nA(0)
                       , fB(1.0)
                       , dtC(__DATETIME__)
                     {
                     };
};

Test pClassTest[];
 
void OnStart()
{
   if (ArrayResize(pClassTest, ARRAY_SIZE) != ARRAY_SIZE)
   {
      Alert("Not enought memory");
      return;
   }
}

Die gleichen 60.000.000 Objekte werden mit einem Standardkonstruktoraufruf zugewiesen. Außerdem ist es nicht notwendig, manuell zu initialisieren und dann Speicher freizugeben, was eine erhebliche Zeitersparnis (um ein Vielfaches) bedeutet und den Code viel sicherer, einfacher und lokaler macht.

Prüfen. Unterbrechen wir und öffnen es im Prozessmanager. Hier in ProcessHacker:

Im privaten Bereich werden 4 bzw. 2 GB zugewiesen.

Überprüfung der Stapelgröße:


Der Skriptstapel beträgt 8 MB, und dies ist der maximale Stapel.

Es ist leicht, die Logik im Kopf anzuwenden und zu berechnen, dass 60 000 000 Objekte mit einer Größe von je 20 Byte über 1 Gbyte Speicherplatz belegen. Kein Stapel wird ausreichen, um alles unterzubringen.

Außerdem weisen beide Proben (mit und ohne Zeiger) das gleiche Profil auf. Auf dem Stapel wird nichts zugewiesen. Das Beispiel mit Zeigern weist jedoch 1 GB mehr Speicher zu, das ist ebenfalls leicht zu erkennen.

d.h. Sie können nicht einfach die maximale Größe des Stacks zur Laufzeit ändern. Die maximale Größe des Stapels ist vordefiniert und wird im Voraus festgelegt, z. B. während der Kompilierung.

s.s. Rein theoretisch ist es möglich, kleine statische Arrays auf dem Stack zu allozieren (in mql wird es nicht explizit sein). Dies kann jedoch zu großen Problemen führen, da der Benutzer leicht mehrere solcher Arrays erstellen kann, sogar in verschiedenen verknüpften Funktionen, und der Stack überläuft. Aus diesem Grund sollten die Benutzer vor solchen Selbstschussanlagen geschützt werden und Arrays unabhängig von ihrer Größe immer im gemeinsamen Speicher zuweisen.

 
Dmitry Fedoseev #:

double x[268435448]; im allgemeinen Teil kompiliert.

268435449 lässt sich nicht mehr kompilieren.

Und268435449 kompiliert in OnStart() des Skripts; ich habe dieses riesige Array x im allgemeinen Abschnitt gelassen.

268435448*8=2.147.483.584 sind zwei Gigabyte.

***

Und hier ist der Grenzwert in der Funktion: double x[268435456];

Dies sind die Grenzen des Codeanalysators. Es ist nicht wirklich ein Problem, 4 oder 6 oder 20 Gb Speicher in mql zuzuweisen, wenn Sie ihn haben.

 
Vasiliy Sokolov #:

immer Arrays im gemeinsamen Speicher zuweisen, unabhängig von ihrer Größe.

Keine statischen Arrays verwenden?