mql5语言的特点、微妙之处以及技巧 - 页 167

 
Igor Makanu:

没想到你在阅读短代码方面会有任何困难,那么请阅读帮助https://www.mql5.com/ru/docs/trading/ordercalcmargin

谢谢,已经弄明白了 )

我刚刚开始学习MQL5。我一定是把我的问题放在了一个错误的地方

 
跨平台的差异ArrayCopy
#property strict

void OnStart()
{
  int Array1[1];
  int Array2[1];
  
  Print(ArrayCopy(Array1, Array2, 0, 0, 0)); // MQL4 - 1, MQL5 - 0
  Print(WHOLE_ARRAY); // MQL4 - 0, MQL5 - -1
}
 
fxsaber:
跨平台的差异ArrayCopy。

很明显,为了不造成任何影响,你必须写出

  Print(ArrayCopy(Array1, Array2, 0, 0, WHOLE_ARRAY));

或者

Print(ArrayCopy(Array1, Array2, 0, 0));

或在此背景下的所有默认

Print(ArrayCopy(Array1, Array2));
 
Artyom Trishkin:

很明显,为了不造成任何影响,你必须写出

或者

或在此背景下的所有默认

问题就在这里。

ArrayCopy(Array1, Array2, 0, 0, GetAmountToCopy());

如果该函数返回0,那么MQL4和MQL5将有不同的结果。

 
fxsaber:

问题就在这里。

如果该函数返回0,MQL4和MQL5将有不同的结果。

所以,GetAmountToCopy()解决了这个问题,以防该函数应该返回零。

比如说。

return(res==0 ? WHOLE_ARRAY : res);
 
fxsaber:

问题就在这里。

如果该函数返回0,MQL4和MQL5将有不同的结果。

我不太清楚你在那里计算什么。GetAmountToCopy()可以有多个返回选项。

如果0是什么都不复制(根据我的理解,这是导致问题的条件),-1是复制整个数组,你显然应该指定0和-1以外的返回值,以防你想什么都不复制。例如,返回 EMPTY_VALUE。在这种情况下,我们也许应该重载ArrayCopy()函数,该函数 将首先检查从GetAmountToCopy()传递给它的内容。如果是EMPTY_VALUE,则退出函数。对于其余的,如果使用WHOLE_ARRAY常数,在MQL5和MQL4中要复制的数据大小将被正确选择。

 
Artyom Trishkin:

你在那里计算的内容不是很清楚。

我不太明白你为什么要写MQL4/5差异的可能实现。我只是为那些写跨平台代码的人指出了这些差异。

这些差异已经积累了一篇文章。应该有人来写。

 
fxsaber:

我不太清楚你为什么要写关于MQL4/5差异的可能变通方法。我只是为那些写跨平台代码的人指出了这些差异。

这些差异已经积累了一篇文章。应该有人来写。

我以为这是个问题。很好。我可以删除我的信息。

 

以前只是怀疑,现在证实了。在处理资源的时候,很容易出现内存泄露的情况。


例子。

#include <Graphics\Graphic.mqh>

#define  MIN_WIDTH 10

// Создание графика.
string GraphPlot( const double &Y[],
                  int Width = 0, int Height = 0, const ENUM_CURVE_TYPE Type = CURVE_NONE,
                  const string CurveName = NULL, string ObjName = NULL )
{
  Width = Width ? Width : (int)::ChartGetInteger(0, CHART_WIDTH_IN_PIXELS);
  Height = Height ? Height : (int)::ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS);
  ObjName = (ObjName == NULL) ? __FUNCTION__ : ObjName;

  CGraphic Graphic;

  const bool Res = (::ObjectFind(0, ObjName) >= 0) ? Graphic.Attach(0, ObjName) : Graphic.Create(0, ObjName, 0, 0, 0, Width, Height);

  if (Res)
  {
    const int Size = ::ArraySize(Y);

    Graphic.CurveAdd(Y, ((Type == CURVE_NONE) && Size) ? ((Width / Size < MIN_WIDTH) ? CURVE_LINES : CURVE_POINTS_AND_LINES) : Type, CurveName);

    Graphic.CurvePlotAll();
    Graphic.Update();
  }

  return (Res ? Graphic.ChartObjectName() : NULL);
}

void OnStart()
{  
  const double Array[] = {0, 1, 2, 3, 4, 5};
      
  const string ObjName = GraphPlot(Array, 1200); // Создали график-объект.
  const string ResourceName = ::ObjectGetString(0, ObjName, OBJPROP_BMPFILE); // К какому ресурсу привязка объекта.
  
  // ObjectDelete(0, ObjName); // Удалили объект.

//  ResourceFree(StringSubstr(ResourceName, StringFind(ResourceName, "::"))); // Без этой строки утечка памяти.
}


一个通过SB的脚本将一个数字数组的图形打印到一个图表上。然后你可以手动删除这个图表(对象),但分配给这个图表的资源将永远以只读模式挂在内存中。它不能被删除,因为只有所有者脚本可以删除它(见高亮行)。


MQL中没有任何功能可以释放如此占用的内存。在VPS上要 特别注意这一点。

 
fxsaber:

以前只是怀疑,现在证实了。在处理资源的时候,很容易出现内存泄露的情况。


例子。


一个通过SB的脚本将一个数字数组的图形打印到一个图表上。然后你可以手动删除这个图表(对象),但分配给这个图表的资源将永远以只读模式挂在内存中。它不能被删除,因为只有所有者脚本可以删除它(见高亮行)。


MQL中没有任何功能可以释放如此占用的内存。在VPS上要 特别小心。

当你收到一条关于内存泄漏的信息时,这意味着没有明确的命令来释放该内存。

当一个程序终止时(也就是你收到这些信息的时候),它释放了所有的内存,包括泄露的内存,在任何情况下。