Aide sur la POO - page 2

 
Ihor Herasko #:
Si vous voulez soudainement vous disputer avec Renate, bienvenue.

euh, comme ça :

Ihor Herasko #:

Une dernière chose. La meilleure façon de créer des tableaux d'objets est d'utiliser un pointeur. Sinon, vous obtenez un tableau dans la mémoire de la pile, qui est très petite :

n'a rien à voir avec ce que dit Renat et les exemples ci-dessus.
 
Ihor Herasko #:

Si vous modifiez un peu l'exemple en faisant la déclaration au niveau local et en mettant un nombre pas si terrible, le compilateur vous dit directement quel est le problème :

Si vous voulez vous disputer avec Renate, vous êtes le bienvenu.

Dans votre exemple :

Test *pClassTest[];

Est définie en dehors de la fonction, comme une variable globale. Alors, quelle est la pile ici ? C'est un tas.

 
Vasiliy Sokolov #:

Dans votre exemple :

est définie en dehors de la fonction comme une variable globale. Alors, quelle est la pile ici ? C'est un tas.

Incroyable ! Vasily, tu t'es lancé dans une discussion sans comprendre le sujet de ton argumentation, et sans faire le moindre effort pour comprendre le sujet de l'argumentation ?

Igor argumente tous les deux dans le tas, et cette ligne de code provient du second exemple ("correct"), qui compile, contrairement au premier, qui ne compile pas (et n'a pas de pointeur dans celui-ci).

 
Ihor Herasko #:

Si vous modifiez un peu l'exemple en faisant la déclaration au niveau local et en mettant un nombre pas si terrible, le compilateur vous dit directement quel est le problème :

Si tu veux soudainement te disputer avec Renate, tu es le bienvenu.

Au sujet de "pas terrible". Comment dire. La pile fait 1 Mo par défaut et vous y allouez ARRAY_SIZE*sizeof(Test), ce qui est évidemment plus grand.

 
Ihor Herasko #:

Ce n'est pas un problème, encore moins un problème potentiel. C'est juste les particularités de la gestion de la mémoire dans MT. Voici un tableau statique :

Et voici un tableau dynamique :

Dans ce cas, tout se compile et fonctionne.

Allons de l'avant.

Dans le premier cas, la mémoire est allouée au moment de la compilation. Autrement dit, le segment .data du programme doit inclure ces ARRAY_SIZE*sizeof(Test). Qu'est-ce qu'il y avait là ARRAY_SIZE ?)) Si je ne me trompe pas, en dessous de 2TB, le fichier .ex5 sort)))).

Dans le second cas, il suffit de mettre l'allocation dans la pile d'octets ARRAY_SIZE*sizeof(Test*), soit 480GB,

 

double x[268435448] ; dans la section générale compile.

268435449 ne compile plus.

Et268435449 compile dans OnStart() du script, et il compile dans la section générale laissant cet énorme tableau x.

268435448*8=2,147,483,584 est deux gigs.

***

Et voici la limite dans la fonction : double x[268435456] ;

 

Voir la référence sur la pile :

Indique la taille de la pile pour le programme MQL5, une taille de pile suffisante est requise en cas d'appels de fonction récursifs.

Lors du lancement d'un script ou d'un Expert Advisor sur un graphique, une pile d'au moins 8 Mb est allouée, pour les indicateurs la propriété ne fonctionne pas - la pile est toujours fixée à 1 Mb.

Lorsqu'il est lancé dans le testeur, le programme alloue toujours une pile de 16 Mo.


Nous devons supposer que la pile n'est utilisée que pour les appels de fonctions récursives. Par conséquent, quelle que soit la taille des tableaux statiques, pour les appels récursifs, la pile restera telle quelle.

 
Dmitry Fedoseev #:

Incroyable ! Vasiliy, vous êtes-vous lancé dans une dispute sans comprendre ce sur quoi vous vous disputez, et sans faire le moindre effort pour comprendre ce sur quoi porte la dispute ?

Igor argumente tous les deux dans le tas, et cette ligne de code provient du second exemple ("correct"), qui compile, par opposition au premier, qui ne compile pas (et ne contient pas de pointeur).

Ok. Je ne comprends pas. Vous comprenez ? Vous comprenez exactement ? Exactement ?

L'argument se résume à l'affirmation suivante :

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading

Aide sur la POO

Ihor Herasko, 2021.09.19 21:00

Et encore une chose. Il est préférable de créer des tableaux d'objets en utilisant un pointeur. Sinon, vous obtiendrez un tableau dans la mémoire de la pile, ce qui est très peu :

Strategy2 *pZ[]; 

Cette affirmation est incorrecte. Les tableaux ne sont pas alloués dans la pile. Ni par le biais de pointeurs, ni de manière statique. C'est facile à vérifier.

Deuxième point : l'exemple utilise des pointeurs mais ils ne sont pas nécessaires à cet endroit. Voici l'exemple équivalent sans le 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;
   }
}

Les mêmes 60 000 000 d'objets sont alloués avec un appel au constructeur par défaut. Et il n'est pas nécessaire d'initialiser manuellement puis de libérer la mémoire, ce qui permet de gagner un temps considérable (plusieurs fois) tout en rendant le code beaucoup plus sûr, plus simple et local.

Vérification. Faisons une pause et ouvrons-le dans le gestionnaire de processus. Ici à ProcessHacker :

Dans la zone privée, 4 et 2 Go sont respectivement alloués.

Vérification de la taille de la pile :


La pile de script est de 8 Mo et c'est la pile maximale.

Il est facile d'appliquer la logique dans votre tête et de calculer que 60 000 000 d'objets d'une taille de 20 octets chacun occuperont plus de 1 Gbyte de mémoire. Aucune pile ne sera suffisante pour tout faire rentrer.

En outre, les deux échantillons (avec et sans pointeurs) donnent le même profilage. Rien n'est alloué dans la pile. Cependant, l'exemple avec les pointeurs alloue 1 Go de mémoire en plus, il est facile de le voir aussi.

Par exemple, vous ne pouvez pas modifier la taille maximale de la pile au moment de l'exécution. La taille maximale de la pile est prédéfinie et fixée au préalable, par exemple lors de la compilation.

s.s. Purement théorique, il est possible d'allouer de petits tableaux statiques sur la pile (dans mql ce ne sera pas explicite). Mais cela peut entraîner de gros problèmes, car l'utilisateur peut facilement créer plusieurs tableaux de ce type, même dans des fonctions liées différentes, et faire déborder la pile. C'est pourquoi les utilisateurs doivent être protégés contre ce genre d'autodestruction et toujours allouer les tableaux dans la mémoire partagée, quelle que soit leur taille.

 
Dmitry Fedoseev #:

double x[268435448] ; dans la section générale compile.

268435449 ne compile plus.

Et268435449 compile dans OnStart() du script; j'ai laissé cet énorme tableau x dans la section générale.

268435448*8=2,147,483,584 est deux gigs.

***

Et voici la limite dans la fonction : double x[268435456] ;

Ce sont les limites de l'analyseur de code. Ce n'est pas vraiment un problème d'allouer 4 ou 6 ou 20 Go de mémoire dans mql si vous en avez.

 
Vasiliy Sokolov #:

allouetoujours les tableaux dans la mémoire partagée, quelle que soit leur taille.

Ne pas utiliser de tableaux statiques ?