对OOP的帮助 - 页 2

 
Ihor Herasko #:
如果你突然想和雷纳特争论,欢迎

呃,像这样。

Ihor Herasko#:

还有一件事。对象数组最好通过一个指针来创建。否则你会在堆栈内存中得到一个数组,而这个数组是非常小的。

与Renat所说的和上面的例子没有关系。
 
Ihor Herasko #:

如果你稍微修改一下这个例子,把声明放在局部级别,并加上一个不那么可怕的数字,编译器会直接告诉你问题出在哪里。

如果你想和雷纳特争论,欢迎 你这样做。

在你的例子中。

Test *pClassTest[];

被定义在函数之外,作为一个全局变量。那么这里的堆栈是什么?它是一个堆。

 
Vasiliy Sokolov #:

在你的例子中。

被定义在函数之外,作为一个全局变量。那么这里的堆栈是什么?这是一个堆。

惊人的!瓦西里,你在不了解你所争论的内容的情况下就陷入了争论,而且没有做出任何努力去了解争论的内容?

Igor在堆中都有争论,这行代码来自第二个("正确的")例子,它可以编译,而不像第一个,它不能编译(而且里面没有指针)。

 
Ihor Herasko #:

如果你稍微修改一下这个例子,把声明放在局部级别,并加上一个不那么可怕的数字,编译器会直接告诉你问题出在哪里。

如果你突然想和雷纳特争论,欢迎你

关于 "不可怕 "的问题。怎么说呢?堆栈默认为1MB,你在上面分配ARRAY_SIZE*sizeof(Test),这显然更大。

 
Ihor Herasko #:

这不是一个问题,更不是一个潜在的问题。这只是MT中内存处理的特殊性。这里是一个静态数组。

而这里是一个动态阵列。

在这种情况下,一切都能编译和工作。

让我们继续前进。

在第一种情况下,内存是在编译时分配的。也就是说,程序的.数据段应该包括这些ARRAY_SIZE*sizeof(Test)。那里的ARRAY_SIZE是什么?))如果我没有弄错的话,在2TB以下,.ex5文件会出来))))

在第二种情况下,只要在ARRAY_SIZE*sizeof(Test*)字节堆中进行分配,即480GB。

 

double x[268435448];在一般部分编译。

268435449已经不能编译了。

268435449 在脚本的OnStart()中编译,在一般部分编译,留下这个巨大的数组X

268435448*8=2,147,483,584是两个G。

***

而这里是函数中的极限: double x[268435456]。

 

见关于堆栈的参考资料。

表示MQL5程序的堆栈 大小,在递归函数调用的情况下需要足够的堆栈大小。

当在图表上启动一个脚本或专家顾问时,至少要分配8Mb的堆栈,对于指标,该属性不起作用--堆栈总是固定在1Mb。

当在测试器中启动时,该程序总是分配16Mb的堆栈。


我们应该假设,堆栈只用于递归函数的调用。因此,无论静态数组的大小如何,对于递归调用,堆栈将保持原状。

 
Dmitry Fedoseev #:

惊人的!瓦西里,你是否在不了解你所争论的内容的情况下就陷入了争论,而且没有做出任何努力去了解争论的内容?

Igor都在堆中争论,这行代码来自第二个("正确的")例子,它可以编译,而第一个则不能编译(而且里面没有指针)。

好的。我不明白。你明白吗?你完全明白吗?究竟是什么?

该论点可归结为以下说法。

关于交易、自动交易系统和交易策略测试的论坛

对OOP的帮助

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。

在私人区域,分别分配4和2GB。

检查堆栈大小。


脚本堆栈是8MB,这是最大的堆栈。

在你的头脑中应用逻辑很容易,计算出60 000 000个对象,每个大小为20字节,将占用超过1 G字节的内存。没有一个堆栈足以装下所有的东西。

此外,两个样本(有指针和无指针)都给出了相同的剖析。堆栈中没有分配任何东西。然而,带指针的例子多分配了1GB的内存,这也很容易看出。

s.e. 你不能在运行时去改变堆栈的最大尺寸。最大的堆栈大小是预先定义的,并事先设定,例如在编译时。

s.s. 纯粹从理论上讲,在栈上分配小的静态数组是可能的(在mql中它不会是显式的)。但这可能导致很大的问题,因为用户可能非常容易地创建几个这样的数组,甚至在不同的链接函数中,从而溢出堆栈。这就是为什么要保护用户不受这种自寻烦恼的影响,总是 在共享内存中分配数组,无论其大小如何。

 
Dmitry Fedoseev #:

double x[268435448];在一般部分编译。

268435449已经不能编译了。

268435449 是在脚本的OnStart()中编译的;我把这个巨大的数组x留在了一般的部分

268435448*8=2,147,483,584是两个G。

***

而这里是函数中的极限: double x[268435456]。

这些是代码分析器的限制。如果你有的话,在mql中分配4或6或20Gb的内存其实不是问题。

 
Vasiliy Sokolov #:

总是 在共享内存中分配数组,无论其大小如何。

不使用静态数组?