Ошибки, баги, вопросы - страница 2794

 
Mihail Matkovskij:

У меня индикатор стал почему-то терять графические объекты и не удаляет их. Использую автоматическое удаление в деструкторе класса. Вызываю:

В результате получаю фальш. Вызываю GetLastError() и получаю ошибку 4101 ("Ошибочный идентификатор графика"). Допустим... Сравниваю chartID удаляемого графического объекта с результатом функции ChartID() и они абсолютно одинаковы. В чём может быть причина не удаления объекта с графика и как это можно обойти?

Решил попробовать по-другому. Во время создания все объекты чарта добавляю в список, а при удалении индикатора удаляю все объекты с помощью цикла. Теперь функция GetLastError() даёт ошибку 4001 после вызова функции ObjectDelete и по прежнему некоторые объекты чарта остаются на графике.

 
Mihail Matkovskij:

У меня индикатор стал почему-то терять графические объекты и не удаляет их. Использую автоматическое удаление в деструкторе класса. Вызываю:

В результате получаю фальш. Вызываю GetLastError() и получаю ошибку 4101 ("Ошибочный идентификатор графика"). Допустим... Сравниваю 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, затем в окне нажать кнопку "List all" и увидеть не удаленные объекты.

Objects

У меня их осталось аж 294 из 100000.

Если уменьшить значение входного параметра nBars, то баг не проявляется.

Файлы:
 

Доброго времени суток.

Долго резину тянул с переходом с Windows 7 на 10, но на неделе переустановил.

Теперь у меня проблема, не могу скачать демо версии экспертов индикаторов своих и чужих,

нажимаю на кнопку скачать и нечего не происходит, при открытом и закрытом терминале пробывал!?

Пробую скачать для терминала МТ4, на МТ5 пока не побывал.

Что за фигня?

 
Mihail Matkovskij:
Сделал исходник, где возникает данный баг:

А что происходит при удалении указателя?

//+------------------------------------------------------------------+
//| 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:

У меня их осталось аж 294 из 100000.

Если уменьшить значение входного параметра 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 два раза подряд и безрезультатно). А функция Sleep в индикаторах не работает, чтобы дать графику немного времени на удаление каждого объекта. Возможно где-нибудь есть примеры, как это обойти?

 
Alexey Viktorov:

А не может получиться так, что цикл длится дольше чем отведено времени на выполнение OnDeinit?

Ведь у вас в примере все объекты имеют префикс "trend" почему-бы не воспользоваться этим и отказаться от цикла?

Это только в примере. В индикаторе же, над которым я работаю довольно сложные имена. А пример я сделал просто для демонстрации.

 
Mihail Matkovskij:

Я конечно же думал раньше об этом примечании. Но потом почему-то решил что это баг терминала. За что приношу свои извинения. Получается, это моя недоработка.

Но я не знаю, что в данном случае делать. Вызывать ObjectDelete, а потом ObjectFind и дожидаться пока он отработает, чтобы узнать, удален ли на самом деле объект. Исходя из того же примечания, это слишком затратно по времени. Да и не знаю, сработает ли повторное удаление (в своем индикаторе я пытался вызывать ObjectDelete два раза подряд и безрезультатно). А функция Sleep в индикаторах не работает, чтобы дать графику немного времени на удаление каждого объекта. Возможно где-нибудь есть примеры, как это обойти?

Вы же по-моему добавляете все указатели в список. Подсистема терминала сама удаляет такие объекты, указатели на которые лежат в списке 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:

После завершения работы терминала после индикатора остаются объекты на чарте. И когда я снова запускаю терминал, то эти объекты видны и портят весь вид.

Я не у компа чтобы проверить ваш пример. Свой пост выше дополнил тем, что вижу по ошибкам.