Errors, bugs, questions - page 2794

 
Mihail Matkovskij:

My indicator has started to lose graphical objects for some reason and does not delete them. I use automatic deletion in class destructor. I call it:

As a result, I get a false positive. I call GetLastError() and get error 4101 ("Errory chart identifier"). Suppose. I compare the chartID of the graphical object being deleted with the ChartID() function result and they are exactly the same. What can be the reason for not removing an object from the chart and how can I get around it?

I have decided to try another way. When creating a chart, I add all objects to the list and use the loop to delete all objects when deleting the indicator. Now functionGetLastError() gives error 4001 after ObjectDeletefunction call and some chart objects stay on the chart.

 
Mihail Matkovskij:

My indicator started losing graphical objects for some reason and won't delete them. I use automatic deletion in class destructor. I call it:

As a result, I get a false positive. I call GetLastError() and get error 4101 ("Errory chart identifier"). Suppose. I compare the chartID of the graphical object being deleted with the ChartID() function result and they are absolutely the same. What may be the reason for not removing an object from the chart and how can it be avoided?

I have made a source code where this bug occurs:
//+------------------------------------------------------------------+
//|                                           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;
  }
}
//+------------------------------------------------------------------+

Actions to demonstrate the bug.

1. place the indicator on the chart.

2. Remove the indicator from the chart.

3 Press Ctrl+B, then press the "List all" button in the window and see the objects that have not been removed.

Objects

I have only 294 out of 100000.

If you reduce the value of input parameter nBars, the bug does not appear.

Files:
 

Good afternoon.

I've been stalling for a long time with upgrading from Windows 7 to 10, but I reinstalled this week.

Now I have a problem, I can't download Expert Advisor demo versions of my indicators and other EAs,

I hit download button and nothing happens, I tried it with opened and closed terminal!

I am trying to download it for MT4 terminal, I haven't been to MT5 yet.

What the hell is going on?

 
Mihail Matkovskij:
Made a source code where this bug occurs:

What happens when a pointer is deleted?

//+------------------------------------------------------------------+
//| 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;
  }
}

Is there a command to the graph to delete the graphical object? See note to ObjectDelete

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

I have as many as 294 out of 100000.

If we decrease the value of input parameter nBars, the bug doesn't occur.

Can it happen that the loop lasts longer than it takes to execute OnDeinit?

In your example all objects have prefix "trend", why don't you use it and refuse from the loop?

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

What happens when a pointer is deleted?

Is there a command to the graph to delete the graphical object? See the note on ObjectDelete

I've certainly thought about this note before. But then I decided for some reason that it was a bug of the terminal. For which I apologize. So it must be my fault.

But I do not know what to do in this case. Do I call ObjectDelete and then ObjectFind and wait until it fails to find out if the object was actually removed? Judging by the same note, it's too time consuming. I do not know if a second deletion will work (in my indicator I have tried to call ObjectDelete twice in a row, but it did not work). And the Sleep function in indicators doesn't work to give the chart some time to delete each object. Perhaps there are examples somewhere on how to get around this?

 
Alexey Viktorov:

Can't it happen that the loop lasts longer than the time allowed to execute OnDeinit?

After all, all objects in your example have "trend" prefix, why not use it and refuse from the loop?

This is only in the example. The indicator I am working with has complex names. And I gave an example just for demonstration purpose.

 
Mihail Matkovskij:

I certainly thought about this note before. But then for some reason I thought it was a terminal bug. For which I apologise. It turns out to be my fault.

But I do not know what to do in this case. Do I call ObjectDelete and then ObjectFind and wait until it fails to find out if the object was actually removed? Judging by the same note, it's too time consuming. I do not know if a second deletion would work (in my indicator I tried to call ObjectDelete twice in a row, but it did not work). And the Sleep function in indicators doesn't work to give the chart some time to delete each object. Perhaps there are examples somewhere of how to get around this?

I think you're adding all pointers to the list. Terminal subsystem itself deletes such objects, pointers to which are in CArrayObj list

trend = new CChartObjectTrend();
    if(trend.Create(0, "trend"+(string)i, 0, time[shift], low[shift], time[shift], high[shift]))
      listOfTrendLines.Add(trend);
Here you have a potential memory leak. And a potential invocation of an invalid object.
 
Artyom Trishkin:
I think you add all pointers to the list. Terminal subsystem itself deletes such objects, pointers to which are in CArrayObj list

After the terminal is shut down, objects remain on the chart after the indicator. And when I start the terminal again, these objects are visible and spoil the whole view.

 
Mihail Matkovskij:

After the terminal is shut down, objects remain on the chart after the indicator. And when I start the terminal again, these objects are visible and spoil the whole view.

I am not at my PC to check your example. I have added to my post above what I see in errors.
Reason: