Ajuda com o OOP - página 2

 
Ihor Herasko #:
Se de repente você quiser discutir com Renate, seja bem-vindo.

er, assim:

Ihor Herasko #:

Mais uma coisa. As matrizes de objetos são melhor criadas através de um ponteiro. Caso contrário, você obtém uma matriz na memória da pilha, que é muito pequena:

não tem nada a ver com o que Renat diz e com os exemplos acima.
 
Ihor Herasko #:

Se você modificar um pouco o exemplo fazendo a declaração a nível local e colocando um número não tão terrível, o compilador lhe diz diretamente qual é o problema:

Se você quiser discutir com Renate, você é bem-vindo a fazê-lo.

Em seu exemplo:

Test *pClassTest[];

É definida fora da função, como uma variável global. Então o que é a pilha aqui? É uma pilha.

 
Vasiliy Sokolov #:

Em seu exemplo:

é definida fora da função como uma variável global. Então o que é a pilha aqui? É uma pilha.

Incrível! Vasily, você entrou numa discussão sem entender sobre o que está discutindo, e sem fazer nenhum esforço para entender do que se trata a discussão?

Igor argumenta ambos na pilha, e esta linha de código é do segundo exemplo ("correto"), que compila, ao contrário do primeiro, que não compila (e não tem ponteiro nele).

 
Ihor Herasko #:

Se você modificar um pouco o exemplo fazendo a declaração a nível local e colocando um número não tão terrível, o compilador lhe diz diretamente qual é o problema:

Se de repente você quiser discutir com Renate, é bem-vindo.

Sobre o tema "não terrível". Como dizer. A pilha é de 1 MB por padrão e você atribui ARRAY_SIZE*sizeof(Test) sobre ela, que é obviamente maior.

 
Ihor Herasko #:

Não é um problema, muito menos um problema potencial. São apenas as peculiaridades do manejo da memória na MT. Aqui está uma matriz estática:

E aqui está uma matriz dinâmica:

Neste caso, tudo se compila e funciona.

Vamos em frente.

No primeiro caso, a memória é alocada em tempo de compilação. Ou seja, o segmento .data do programa deve incluir estes ARRAY_SIZE*sizeof(Test). O que ARRAY_SIZE estava lá?)) Se não estou enganado, sob o arquivo 2TB .ex5 sai))))

No segundo caso, basta fazer a alocação na pilha de bytes de tamanho ARRAY_SIZE*(Test*), ou seja, 480GB,

 

duplo x[268435448]; na seção geral compila.

268435449 não compila mais.

E268435449 compila em OnStart() do roteiro; eu deixei este enorme array x na seção geral.

268435448*8=2.147.483.584 é de dois gigs.

***

E aqui está o limite da função: duplo x[268435456];

 

Ver referência sobre a pilha:

Indica o tamanho da pilha para o programa MQL5, é necessário um tamanho de pilha suficiente no caso de chamadas recursivas de funções.

Ao lançar um roteiro ou um Expert Advisor em um gráfico, uma pilha de pelo menos 8 Mb é alocada, para os indicadores a propriedade não funciona - a pilha é sempre fixada em 1 Mb.

Quando lançado no testador, o programa sempre aloca uma pilha de 16 Mb.


Devemos supor que a pilha é usada apenas para chamadas recursivas de funções. Portanto, não importa o tamanho das matrizes estáticas, para chamadas recursivas a pilha permanecerá como está.

 
Dmitry Fedoseev #:

Incrível! Vasiliy, você entrou em uma discussão sem entender sobre o que está discutindo, e sem fazer nenhum esforço para entender do que se trata a discussão?

Igor argumenta ambos na pilha, e esta linha de código é do segundo exemplo ("correto"), que compila, ao contrário do primeiro, que não compila (e não tem ponteiro nele).

Ok. Eu não entendo. Você entendeu? Você entendeu exatamente? Exatamente?

O argumento se resume à seguinte declaração:

Fórum sobre comércio, sistemas automatizados de comércio e testes de estratégia comercial

Ajuda com o OOP

Ihor Herasko, 2021.09.19 21:00

E mais uma coisa. É melhor criar matrizes de objetos usando um ponteiro. Caso contrário, você terá uma matriz na memória da pilha, que é muito pequena:

Strategy2 *pZ[]; 

Esta é uma afirmação incorreta. As matrizes não são alocadas na pilha. Nem através de indicadores nem estaticamente. Isto é fácil de verificar.

O segundo ponto: o exemplo usa apontadores, mas eles não são necessários ali. Aqui está o exemplo equivalente sem a chapa nua:

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

Os mesmos 60.000.000 de objetos são alocados com uma chamada padrão do construtor. E não há necessidade de inicializar manualmente e depois liberar a memória, o que economiza tempo significativo (muitas vezes) enquanto torna o código muito mais seguro, mais simples e local.

Verificação. Vamos quebrá-lo e abri-lo no gerente de processo. Aqui em ProcessHacker:

Na área privada, 4 e 2 GB são alocados respectivamente.

Verificação do tamanho da pilha:


A pilha do roteiro é de 8 MB e esta é a pilha máxima.

É fácil aplicar a lógica em sua cabeça e calcular que 60 000 000 de objetos do tamanho de 20 bytes cada um ocupará mais de 1 Gbyte de memória. Nenhuma pilha será suficiente para encaixar tudo isso.

Além disso, ambas as amostras (com e sem indicadores) dão o mesmo perfil. Nada é alocado na pilha. No entanto, o exemplo com apontadores aloca mais 1 GB de memória, é fácil de ver isso também.

s.e. Você não pode simplesmente mudar o tamanho máximo da pilha em tempo de execução. O tamanho máximo da pilha é pré-definido e definido previamente, por exemplo, durante a compilação.

s.s. Pura e teoricamente, é possível alocar pequenas matrizes estáticas na pilha (em mql não será explícito). Mas isso pode levar a grandes problemas, pois o usuário pode facilmente criar vários desses conjuntos, mesmo em diferentes funções ligadas, e transbordar a pilha. É por isso que os usuários devem ser protegidos de tal auto-shooting e sempre alocar arrays na memória compartilhada, independentemente de seu tamanho.

 
Dmitry Fedoseev #:

duplo x[268435448]; na seção geral compila.

268435449 não compila mais.

E268435449 compila em OnStart() do roteiro; eu deixei este enorme array x na seção geral.

268435448*8=2.147.483.584 é de dois gigs.

***

E aqui está o limite da função: duplo x[268435456];

Estas são as limitações do analisador de código. Não é realmente um problema alocar 4 ou 6 ou 20 Gb de memória em mql, se você a tiver.

 
Vasiliy Sokolov #:

sempre alocar arrays em memória compartilhada, independentemente de seu tamanho.

Não usar arrays estáticos?

Razão: