Ayuda con la POO - página 2

 
Ihor Herasko #:
Si de repente quieres discutir con Renate, bienvenido sea.

er, así:

Ihor Herasko #:

Una cosa más. Las matrices de objetos se crean mejor mediante un puntero. De lo contrario, se obtiene una matriz en la memoria de la pila, que es muy pequeña:

no tiene nada que ver con lo que dice Renat y los ejemplos anteriores.
 
Ihor Herasko #:

Si modificas un poco el ejemplo haciendo la declaración a nivel local y poniendo un número no tan terrible, el compilador te dice directamente cuál es el problema:

Si alguna vez quieres discutir con Renate, eres bienvenido a hacerlo.

En su ejemplo:

Test *pClassTest[];

Se define fuera de la función, como una variable global. Entonces, ¿cuál es la pila aquí? Es un montón.

 
Vasiliy Sokolov #:

En su ejemplo:

se define fuera de la función como una variable global. Entonces, ¿cuál es la pila aquí? Es un montón.

¡Increíble! Vasily, ¿te has metido en una discusión sin entender lo que estás discutiendo y sin hacer ningún esfuerzo por entender de qué va la discusión?

Igor argumenta ambos en el montón, y esta línea de código es del segundo ejemplo ("correcto"), que compila, a diferencia del primero, que no compila (y no tiene ningún puntero en él).

 
Ihor Herasko #:

Si modificas un poco el ejemplo haciendo la declaración a nivel local y poniendo un número no tan terrible, el compilador te dice directamente cuál es el problema:

Si de repente quieres discutir con Renate, eres bienvenido.

Sobre el tema "no es terrible". Cómo se dice. La pila es de 1 MB por defecto y en ella se asigna ARRAY_SIZE*sizeof(Test), que obviamente es mayor.

 
Ihor Herasko #:

No es un problema, y mucho menos un problema potencial. Son las peculiaridades del manejo de la memoria en MT. Aquí hay una matriz estática:

Y aquí hay una matriz dinámica:

En este caso, todo se compila y funciona.

Sigamos adelante.

En el primer caso, la memoria se asigna en tiempo de compilación. Es decir, el segmento .data del programa debe incluir estos ARRAY_SIZE*sizeof(Test). ¿Qué era ARRAY_SIZE ahí?) Si no me equivoco, por debajo de 2TB el archivo .ex5 sale))))

En el segundo caso, sólo va la asignación en el montón de bytes ARRAY_SIZE*sizeof(Test*), es decir, 480GB,

 

double x[268435448]; en la sección general compila.

268435449 ya no compila.

Y268435449 compila en OnStart() del script; dejé este enorme array x en la sección general.

268435448*8=2.147.483.584 son dos gigas.

***

Y aquí está el límite en la función: double x[268435456];

 

Ver referencia sobre la pila:

Indica el tamaño de la p ila para el programa MQL5, se requiere un tamaño de pila suficiente en caso de llamadas a funciones recursivas.

Cuando se lanza un script o un Asesor Experto en un gráfico, se asignan al menos 8 Mb de pila, para los indicadores la propiedad no funciona - la pila siempre se fija en 1 Mb.

Cuando se lanza en el probador, el programa siempre asigna una pila de 16 Mb.


Debemos suponer que la pila se utiliza sólo para las llamadas a funciones recursivas. Por lo tanto, no importa el tamaño de las matrices estáticas, para las llamadas recursivas la pila permanecerá tal cual.

 
Dmitry Fedoseev #:

¡Increíble! Vasiliy, ¿te has metido en una discusión sin entender lo que estás discutiendo y sin hacer ningún esfuerzo por entender de qué va la discusión?

Igor está argumentando en el montón, y esta línea de código es del segundo ejemplo ("correcto"), que compila, a diferencia del primero, que no compila (y no tiene ningún puntero).

Bien. No lo entiendo. ¿Lo entiendes? ¿Lo entiendes exactamente? ¿Exactamente?

El argumento se reduce a la siguiente afirmación:

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

Ayuda con la POO

Ihor Herasko, 2021.09.19 21:00

Y una cosa más. Es mejor crear matrices de objetos utilizando un puntero. De lo contrario, obtendrá una matriz en la memoria de la pila que es muy poco:

Strategy2 *pZ[]; 

Esta afirmación es incorrecta. Las matrices no se asignan en la pila. Ni a través de punteros ni estáticamente. Esto es fácil de comprobar.

El segundo punto: el ejemplo utiliza punteros pero no son necesarios allí. Aquí está el ejemplo equivalente sin la placa desnuda:

#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;
   }
}

Los mismos 60.000.000 de objetos se asignan con una llamada al constructor por defecto. Y no hay necesidad de inicializar manualmente y luego liberar la memoria, lo que ahorra mucho tiempo (muchas veces) y hace que el código sea mucho más seguro, simple y local.

Comprobación. Rompamos y abramos en el administrador de procesos. Aquí en ProcessHacker:

En la zona privada se asignan 4 y 2 GB respectivamente.

Comprobación del tamaño de la pila:


La pila de scripts es de 8 MB y esta es la pila máxima.

Es fácil aplicar la lógica en tu cabeza y calcular que 60 000 000 de objetos de 20 bytes cada uno ocuparán más de 1 Gbyte de memoria. Ninguna pila será suficiente para que quepa todo.

Además, ambas muestras (con y sin punteros) dan el mismo perfil. No se asigna nada en la pila. Sin embargo, el ejemplo con punteros asigna 1 GB más de memoria, es fácil verlo también.

Ten en cuenta que no puedes cambiar el tamaño máximo de la pila en tiempo de ejecución. El tamaño máximo de la pila está predefinido y establecido de antemano, por ejemplo, durante la compilación.

s.d. En pura teoría, es posible asignar pequeñas matrices estáticas en la pila (en mql no será explícito). Pero puede dar lugar a grandes problemas, porque el usuario puede crear fácilmente varias de estas matrices, incluso en diferentes funciones enlazadas, y así desbordar la pila. Por ello, los usuarios deben protegerse de este tipo de autodisparos y asignar siempre arrays en memoria compartida, independientemente de su tamaño.

 
Dmitry Fedoseev #:

double x[268435448]; en la sección general compila.

268435449 ya no compila.

Y268435449 compila en OnStart() del script; dejé este enorme array x en la sección general.

268435448*8=2.147.483.584 son dos gigas.

***

Y aquí está el límite en la función: double x[268435456];

Estas son las limitaciones del analizador de código. No es realmente un problema asignar 4 o 6 o 20 Gb de memoria en mql si lo tienes.

 
Vasiliy Sokolov #:

siempre asignan matrices en la memoria compartida, independientemente de su tamaño.

¿No utilizar matrices estáticas?

Razón de la queja: