Aiuto con OOP - pagina 2

 
Ihor Herasko #:
Se improvvisamente vuoi discutere con Renate, benvenuto.

come questo:

Ihor Herasko #:

Un'altra cosa. Gli array di oggetti sono meglio creati tramite un puntatore. Altrimenti si ottiene un array nella memoria dello stack, che è molto piccolo:

non ha niente a che vedere con quello che dice Renat e con gli esempi di cui sopra.
 
Ihor Herasko #:

Se modificate un po' l'esempio facendo la dichiarazione a livello locale e mettendo un numero non così terribile, il compilatore vi dice direttamente qual è il problema:

Se vuoi discutere con Renate, sei il benvenuto a farlo.

Nel suo esempio:

Test *pClassTest[];

È definito all'esterno della funzione, come variabile globale. Quindi qual è la pila qui? È un mucchio.

 
Vasiliy Sokolov #:

Nel suo esempio:

è definito all'esterno della funzione come variabile globale. Quindi qual è la pila qui? È un mucchio.

Incredibile! Vasily, sei entrato in una discussione senza capire di cosa stai discutendo, e senza fare alcuno sforzo per capire di cosa si tratta?

Igor argomenta entrambi nell'heap, e questa linea di codice è del secondo esempio ("corretto"), che compila, a differenza del primo, che non compila (e non ha alcun puntatore in esso).

 
Ihor Herasko #:

Se modificate un po' l'esempio facendo la dichiarazione a livello locale e mettendo un numero non così terribile, il compilatore vi dice direttamente qual è il problema:

Se improvvisamente vuoi discutere con Renate, sei il benvenuto.

A proposito di "non terribile". Come dire. Lo stack è di 1 MB per impostazione predefinita e si alloca ARRAY_SIZE*sizeof(Test) su di esso, che è ovviamente più grande.

 
Ihor Herasko #:

Non è un problema, tanto meno un problema potenziale. Sono solo le peculiarità della gestione della memoria in MT. Qui c'è un array statico:

Ed ecco un array dinamico:

In questo caso, tutto si compila e funziona.

Andiamo avanti.

Nel primo caso, la memoria è allocata al momento della compilazione. Cioè, il segmento .data del programma dovrebbe includere questi ARRAY_SIZE*sizeof(Test). Cos'era ARRAY_SIZE lì?)) Se non mi sbaglio, sotto i 2TB il file .ex5 esce))))

Nel secondo caso, va solo l'allocazione nel mucchio di byte ARRAY_SIZE*sizeof(Test*), cioè 480GB,

 

doppio x[268435448]; nella sezione generale compila.

268435449 non compila più.

E268435449 compila in OnStart() dello script; ho lasciato questo enorme array x nella sezione generale.

268435448*8=2.147.483.584 sono due giga.

***

Ed ecco il limite nella funzione: doppio x[268435456];

 

Vedere il riferimento sullo stack:

Indica la dimensione dello stack per il programma MQL5, è necessaria una dimensione sufficiente dello stack in caso di chiamate di funzioni ricorsive.

Quando si lancia uno script o un Expert Advisor su un grafico, vengono allocati almeno 8 Mb di stack, per gli indicatori la proprietà non funziona - lo stack è sempre fisso a 1 Mb.

Quando viene lanciato nel tester, il programma alloca sempre uno stack di 16 Mb.


Dobbiamo supporre che lo stack sia usato solo per le chiamate di funzioni ricorsive. Pertanto, non importa quale sia la dimensione degli array statici, per le chiamate ricorsive lo stack rimarrà così com'è.

 
Dmitry Fedoseev #:

Incredibile! Vasiliy, ti sei messo a discutere senza capire di cosa stai discutendo e senza fare alcuno sforzo per capire di cosa si tratta?

Igor argomenta entrambi nell'heap, e questa linea di codice è del secondo esempio ("corretto"), che compila, al contrario del primo, che non compila (e non ha alcun puntatore in esso).

Ok. Non capisco. Hai capito? Hai capito esattamente? Esattamente?

L'argomento si riduce alla seguente affermazione:

Forum sul trading, sistemi di trading automatico e test di strategie di trading

Aiuto con OOP

Ihor Herasko, 2021.09.19 21:00

E un'altra cosa. È meglio creare array di oggetti usando un puntatore. Altrimenti otterrete un array nella memoria dello stack che è molto poco:

Strategy2 *pZ[]; 

Questa è un'affermazione errata. Gli array non sono allocati nello stack. Né attraverso puntatori né staticamente. Questo è facile da controllare.

Il secondo punto: l'esempio usa i puntatori ma non sono necessari. Ecco l'esempio equivalente senza la 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;
   }
}

Gli stessi 60.000.000 di oggetti sono allocati con una chiamata predefinita al costruttore. E non c'è bisogno di inizializzare manualmente e poi liberare la memoria, il che fa risparmiare molto tempo (molte volte) e rende il codice molto più sicuro, semplice e locale.

Controllo. Rompiamo e apriamo in Process Manager. Qui in ProcessHacker:

Nell'area privata, 4 e 2 GB sono allocati rispettivamente.

Controllo della dimensione dello stack:


Lo stack degli script è di 8 MB e questo è lo stack massimo.

È facile applicare la logica nella vostra testa e calcolare che 60 000 000 oggetti di 20 byte ciascuno occuperanno più di 1 Gbyte di memoria. Nessuna pila sarà sufficiente per metterci tutto dentro.

Inoltre, entrambi i campioni (con e senza puntatori) danno lo stesso profilo. Niente è allocato nello stack. Tuttavia, l'esempio con i puntatori alloca 1 GB di memoria in più, è facile vedere anche questo.

s.e. Non si può semplicemente cambiare la dimensione massima dello stack a runtime. La dimensione massima dello stack è predefinita e impostata in anticipo, ad esempio durante la compilazione.

s.s. Puramente in teoria, è possibile allocare piccoli array statici sullo stack (in mql non sarà esplicito). Ma può portare a grossi problemi, perché l'utente può facilmente creare diversi array di questo tipo, anche in diverse funzioni collegate, e far traboccare lo stack. Questo è il motivo per cui gli utenti dovrebbero essere protetti da questo tipo di autocombustione e allocare sempre gli array nella memoria condivisa, indipendentemente dalla loro dimensione.

 
Dmitry Fedoseev #:

doppio x[268435448]; nella sezione generale compila.

268435449 non compila più.

E268435449 compila in OnStart() dello script; ho lasciato questo enorme array x nella sezione generale.

268435448*8=2.147.483.584 sono due giga.

***

Ed ecco il limite nella funzione: doppio x[268435456];

Questi sono i limiti dell'analizzatore di codice. Non è davvero un problema allocare 4 o 6 o 20 Gb di memoria in mql se ne avete.

 
Vasiliy Sokolov #:

allocasempre gli array nella memoria condivisa indipendentemente dalla loro dimensione.

Non usare gli array statici?