错误、漏洞、问题 - 页 2794

 
Mihail Matkovskij:

我的指标由于某种原因开始丢失图形对象,并且不删除它们。我在类的析构器中使用自动删除。我称它为。

结果,我得到一个假阳性。我调用GetLastError(),得到错误4101("Errorychart identifier")。假设。我比较了被删除的图形对象的chartID和ChartID()函数的结果,它们是完全一样的。没有从图表中删除一个对象的原因可能是什么,我怎样才能绕过它?

我已经决定尝试另一种方式。在创建图表时,我将所有对象添加到列表中,并在删除指标时使用循环来删除所有对象。现在函数GetLastError()在调用 ObjectDelete函数后给出错误4001,一些图表对象留在图表上。

 
Mihail Matkovskij:

我的指标由于某种原因开始丢失图形对象,并且不删除它们。我在类的析构器中使用自动删除。我称它为。

结果,我得到一个假阳性。我调用GetLastError(),得到错误4101("Errorychart identifier")。假设。我比较了被删除的图形对象的chartID和ChartID()函数的结果,它们是完全一样的。没有从图表中删除一个对象的原因可能是什么,我怎样才能绕过它?

我做了一个源码,其中出现了这个错误。
//+------------------------------------------------------------------+
//|                                           DeleteChartObjects.mq5 |
//|                                      Copyright 2020, © Cyberdev. |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, © Cyberdev."
#property version   "1.00"
#property indicator_chart_window

#property indicator_plots 0

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

#include <ChartObjects\ChartObjectsLines.mqh>
#include <Arrays\ArrayObj.mqh>

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//--- input parameters
input int      nBars = 100000;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int customN_Bars = 0;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CArrayObj listOfTrendLines;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {
//--- indicator buffers mapping
  int totalBars = iBars(NULL, PERIOD_CURRENT);
  customN_Bars = (nBars < totalBars) ? nBars : totalBars;
//---
  return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[]
) {
  CChartObjectTrend * trend;
  int delta = rates_total - customN_Bars;
  int shift;
  int i;
  for(i = 0; i < customN_Bars; i++) {
    shift = delta + customN_Bars - i - 1;
    trend = new CChartObjectTrend();
    if(trend.Create(0, "trend"+(string)i, 0, time[shift], low[shift], time[shift], high[shift]))
      listOfTrendLines.Add(trend);
  }
  return(rates_total);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
  
  CChartObjectTrend * trend;
  
  int i = listOfTrendLines.Total() - 1;
  for(; i >= 0; i--) {
    trend = dynamic_cast <CChartObjectTrend *> (listOfTrendLines.At(i));
    
    if(CheckPointer(trend) == POINTER_INVALID)
      continue;
    
    delete trend;
  }
}
//+------------------------------------------------------------------+

展示该错误的行动。

1.将指标放在图表上。

2.从图表中删除指标。

3 按Ctrl+B,然后按窗口中的 "列出所有 "按钮,就可以看到未被删除的对象。

物品

我在100000人中有多达294人。

如果你减少输入参数nBars的值,这个错误就不会出现。

附加的文件:
 

下午好。

我从Windows 7升级到10已经拖延了很久,但本周我重新安装了。

现在我有一个问题,我无法下载我的指标和其他EA的专家顾问演示版本。

我点击了下载按钮,但什么也没有发生,我在打开和关闭的终端 上都试过了!我想知道为什么?

我想下载的是MT4终端,我还没有去过MT5。

这到底是怎么回事?

 
Mihail Matkovskij:
做了一个源码,这个bug发生在这里。

当一个指针被删除时会发生什么?

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
  
  CChartObjectTrend * trend;
  
  int i = listOfTrendLines.Total() - 1;
  for(; i >= 0; i--) {
    trend = dynamic_cast <CChartObjectTrend *> (listOfTrendLines.At(i));
    
    if(CheckPointer(trend) == POINTER_INVALID)
      continue;
    
    delete trend;
  }
}

对图形有一个删除图形对象的命令吗?见ObjectDelete 的注释

Документация по MQL5: Графические объекты / ObjectDelete
Документация по MQL5: Графические объекты / ObjectDelete
  • www.mql5.com
При вызове ObjectDelete() всегда используется асинхронный вызов, поэтому функция возвращает только результат постановки команды в очередь графика. В этом случае true означает только то, что команда успешно поставлена в очередь, сам результат её выполнения неизвестен. Для проверки результата выполнения можно использовать функцию ObjectFind() или...
 
Mihail Matkovskij:

我在100000 人中有多达294人。

如果我们降低输入参数nBars的值,这个错误就不会发生。

会不会发生循环持续的时间超过执行OnDeinit的时间?

在你的例子中,所有的对象都有前缀 "trend",你为什么不使用它而拒绝循环?

int  ObjectsDeleteAll(
   long           chart_id,   // идентификатор графика
   const string     prefix,   // префикс имени объекта
   int       sub_window=-1,   // индекс окна
   int      object_type=-1    // тип объекта для удаления
   );
 
Rashid Umarov:

当一个指针被删除时会发生什么?

对图形有一个删除图形对象的命令吗?见关于ObjectDelete 的说明

我当然也曾想过这个注意。但后来我出于某种原因决定,这是一个终端的错误。对此我表示歉意。所以这一定是我的错。

但我不知道在这种情况下该怎么做。我是否要先调用ObjectDelete,然后再调用ObjectFind, 等到它失败后再找出对象是否真的被删除?从同一个说明来看,这太耗费时间了。我不知道第二次删除是否有效(在我的指标中,我曾试图连续调用ObjectDelete两次,但没有成功)。而指标中的 "睡眠 "功能并不能给图表一些时间来删除每个对象。也许某处有关于如何绕过这个问题的例子?

 
Alexey Viktorov:

难道不会发生循环持续的时间超过执行OnDeinit的时间吗?

毕竟,你的例子中的所有对象都有 "trend "前缀,为什么不使用它而拒绝循环呢?

这只是在例子中。我所使用的指标有复杂的名称。我举了一个例子,只是为了示范。

 
Mihail Matkovskij:

我以前当然想过这个注意。但后来不知道为什么,我认为这是一个终端错误。对此我表示歉意。事实证明是我的错。

但我不知道在这种情况下该怎么做。我是否要先调用ObjectDelete,然后再调用ObjectFind, 等到它失败后再找出对象是否真的被删除?从同一个说明来看,这太耗费时间了。我不知道第二次删除是否有效(在我的指标中,我曾试图连续调用ObjectDelete两次,但没有成功)。而指标中的 "睡眠 "功能并不能给图表一些时间来删除每个对象。也许某处有关于如何绕过这个问题的例子?

我想你是把所有的指针都加进去了。终端子系统本身会删除这些对象,这些对象的指针在CArrayObj 列表中。

trend = new CChartObjectTrend();
    if(trend.Create(0, "trend"+(string)i, 0, time[shift], low[shift], time[shift], high[shift]))
      listOfTrendLines.Add(trend);
这里你有一个潜在的内存泄漏。还有可能调用一个无效的对象。
 
Artyom Trishkin:
我想你把所有的指针都加进去。终端子系统本身会删除这些对象,这些对象的指针在CArrayObj列表中。

终端关闭后,对象在指标后仍留在图表上。而当我再次启动终端 时,这些对象是可见的,并破坏了整个视图。

 
Mihail Matkovskij:

终端关闭后,对象在指标后仍留在图表上。而当我再次启动终端 时,这些对象是可见的,并破坏了整个视图。

我不在我的电脑前,无法检查你的例子。我在上面的帖子中补充了我所看到的错误。
原因: