Помогите с ООП - страница 2

 
Ihor Herasko #:
Если вдруг захотите поспорить в Ренатом, то велкам.

эээ как бы вот это:

Ihor Herasko #:

И еще один момент. Массивы объектов лучше создавать через указатель. Иначе получится массив в стековой памяти, которой очень мало:

не имеет ничего общего с тем что говорит Ренат и с приведенными выше примерами.
 
Ihor Herasko #:

Если чуток изменить пример, сделав объявление на локальном уровне и поставив не такое уж и страшное число, то компилятор уже прямым текстом пишет о том, в чем именно дело:

Если вдруг захотите поспорить в Ренатом, то велкам.

В вашем же примере:

Test *pClassTest[];

 определяется вне функции, как глобальная переменная. Так какой здесь стек? Это куча.

 
Vasiliy Sokolov #:

В вашем же примере:

 определяется вне функции, как глобальная переменная. Так какой здесь стек? Это куча.

Потрясающе! Василий, вы полезли в спор, не понимая о чем спорите, и не прилагая усилий, чтобы понять о чем спор?

Игорь и утверждает, что надо в куче, и эта строка кода из второго ("правильного") примера, который компилируется, в отличие от первого, который не компилируется (и в нем нет указателя). 

 
Ihor Herasko #:

Если чуток изменить пример, сделав объявление на локальном уровне и поставив не такое уж и страшное число, то компилятор уже прямым текстом пишет о том, в чем именно дело:

Если вдруг захотите поспорить в Ренатом, то велкам.

На счет "не страшного". Как сказать. Стек по умолчанию 1МБ, а вы выделяете на нем ARRAY_SIZE*sizeof(Test), что явно больше

 
Ihor Herasko #:

Это не проблема и тем более не потенциальная. Просто особенности работы с памятью в МТ. Вот статический массив:

А вот динамический массив:

В этом случае все компилируется и работает.

Идем дальше.

В первом случае память выделяется на этапе компиляции. То есть сегмент .data программы должен включать эти ARRAY_SIZE*sizeof(Test). Сколько там ARRAY_SIZE был?))) Если не ошибаюсь, то под 2ТБ .ex5 файл выходит))))

Во втором случае, как раз идет выделение в куче ARRAY_SIZE*sizeof(Test*) байт, т.е. 480ГБ, 

 

double x[268435448]; в общем разделе компилируется.

268435449 - уже не компилируется

А в OnStart() скрипта 268435449 компилируется, причем в общем разделе оставил этот громадный массив x.

268435448*8=2 147 483 584 - это два гига. 

***

А вот предел в функции: double x[268435456];

 

Смотрите в справе про стек:

Указывает размер стека для MQL5 программы, стек достаточного объема требуется в случае выполнения рекурсивных вызовов функций.

При запуске скрипта или эксперта на графике выделяется стек не менее 8Мб, для индикаторов свойство не работает  - стек всегда фиксированного объема в 1Мб.

При запуске в тестере программе всегда выделяется стек в размере 16 Мб.


Надо полагать, стек используется только для рекурсивного вызова функций. Поэтому неважно какого размера будут статические массивы, для рекурсивного вызова стек останется таким, какой он есть. 

 
Dmitry Fedoseev #:

Потрясающе! Василий, вы полезли в спор, не понимая о чем спорите, и не прилагая усилий, чтобы понять о чем спор?

Игорь и утверждает, что надо в куче, и эта строка кода из второго ("правильного") примера, который компилируется, в отличие от первого, который не компилируется (и в нем нет указателя). 

Ок. Я не понимаю. А вы понимаете? Точно понимаете? Точно точно?

Спор сводится к следующему утверждению:

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Помогите с ООП

Ihor Herasko, 2021.09.19 21:00

И еще один момент. Массивы объектов лучше создавать через указатель. Иначе получится массив в стековой памяти, которой очень мало:

Strategy2 *pZ[]; 

Это неверное утверждение. Массивы в стеке не выделяются. Ни через указатели ни статически. Это легко проверить. 

Второй момент: в примере используются указатели, но они там не нужны. Вот эквивалентный пример без болерплейта:

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

Выделяются те же 60 000 000 объектов с вызовом конструктора по умолчанию. При этом не надо вручную инициализировать, а потом освобождать память, что значительно (в разы) экономит время а код делает гораздо более безопасным простым и локаничным. 

Проверяем. Делаем брейк и открываем в менеждере процессов. Вот в ProcessHacker:

В области private выделино 4 и 2 Гб соотвественно. 

Проверяем размер стеков:


Стек скрипта 8 Мб и это максимальный стек.

Легко включить логику в голове и посчитать, что 60 000 000 объектов размером по 20 байт каждый займут  более 1 Гбайта памяти. Ни какого стека не хватит что бы вместить это в себя.

При этом оба примера (и с указателями и без) дают то же профилирование. В стеке ничего не выделяется. Однако пример с указателями выделяет на 1 Гб больше памяти, в этом тоже легко убедится.

з.ы. Нельзя просто так взять и изменить максимальный размер стека во время выполнения программы. Максимальный размер стека является предопределенным и задается заранее, например при компиляции. 

з.ы.ы. Чисто теоретически возможно небольшие статические массивчики выделять на стеке ( в mql это будет не явно). Но это может привести к большим проблемам, так как пользователь очень лекго может создать несколько таких массивов даже в разных сопряженных функциях и тем самым переполнить стек. Поэтому от такого самострела пользователей нужно обезопасить и всегда выделять массивы в общей памяти независимо от их размера.

 
Dmitry Fedoseev #:

double x[268435448]; в общем разделе компилируется.

268435449 - уже не компилируется

А в OnStart() скрипта 268435449 компилируется, причем в общем разделе оставил этот громадный массив x.

268435448*8=2 147 483 584 - это два гига. 

***

А вот предел в функции: double x[268435456];

Это ограничения анализатора кода. Ведь нет на самом деле ни каких проблем выделить ни 4 ни 6 ни 20 Гб памяти в mql, если она есть.

 
Vasiliy Sokolov #:

всегда выделять массивы в общей памяти независимо от их размера.

Не использовать статические массивы?