Errori, bug, domande - pagina 2794

 
Mihail Matkovskij:

Il mio indicatore ha iniziato a perdere oggetti grafici per qualche motivo e non li cancella. Uso la cancellazione automatica nel distruttore di classe. Io lo chiamo:

Di conseguenza, ottengo un falso positivo. Chiamo GetLastError() e ottengo l'errore 4101 ("Errory chart identifier"). Supponiamo. Confronto il chartID dell'oggetto grafico che viene cancellato con il risultato della funzione ChartID() e sono assolutamente identici. Quale può essere la ragione per cui non si rimuove un oggetto dal grafico e come posso aggirarla?

Ho deciso di provare un altro modo. Quando creo un grafico, aggiungo tutti gli oggetti alla lista e uso il ciclo per cancellare tutti gli oggetti quando cancello l'indicatore. Ora la funzioneGetLastError() dà errore 4001 dopo la chiamata della funzione ObjectDelete e alcuni oggetti del grafico rimangono sul grafico.

 
Mihail Matkovskij:

Il mio indicatore ha iniziato a perdere oggetti grafici per qualche motivo e non li cancella. Uso la cancellazione automatica nel distruttore di classe. Io lo chiamo:

Di conseguenza, ottengo un falso positivo. Chiamo GetLastError() e ottengo l'errore 4101 ("Errory chart identifier"). Supponiamo. Confronto il chartID dell'oggetto grafico cancellato con il risultato della funzione ChartID() e sono esattamente gli stessi. Quale può essere la ragione per cui non si rimuove un oggetto dal grafico e come posso aggirarla?

Ho fatto un codice sorgente dove si verifica questo bug:
//+------------------------------------------------------------------+
//|                                           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;
  }
}
//+------------------------------------------------------------------+

Azioni per dimostrare il bug.

1. posizionare l'indicatore sul grafico.

2. Rimuovere l'indicatore dal grafico.

3 Premi Ctrl+B, poi premi il pulsante "List all" nella finestra e vedi gli oggetti che non sono stati rimossi.

Oggetti

Ne ho addirittura 294 su 100000.

Se si riduce il valore del parametro di input nBars, il bug non appare.

File:
 

Buon pomeriggio.

Ho temporeggiato a lungo con l'aggiornamento da Windows 7 a 10, ma ho reinstallato questa settimana.

Ora ho un problema, non posso scaricare le versioni demo di Expert Advisor dei miei indicatori e di altri EA,

Ho premuto il pulsante di download e non succede niente, ho provato con il terminale aperto e chiuso!

Sto cercando di scaricarlo per il terminale MT4, non sono ancora passato a MT5.

Che diavolo sta succedendo?

 
Mihail Matkovskij:
Fatto un codice sorgente dove si verifica questo bug:

Cosa succede quando un puntatore viene cancellato?

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

C'è un comando al grafico per cancellare l'oggetto grafico? Vedere la nota a ObjectDelete

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

Ne ho addirittura 294 su 100000.

Se diminuiamo il valore del parametro di input nBars, il bug non si verifica.

Può succedere che il ciclo duri più a lungo del tempo necessario per eseguire OnDeinit?

Nel tuo esempio tutti gli oggetti hanno il prefisso "trend", perché non lo usi e rifiuti dal ciclo?

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

Cosa succede quando un puntatore viene cancellato?

C'è un comando al grafico per cancellare l'oggetto grafico? Vedere la nota su ObjectDelete

Ho certamente pensato a questa nota prima. Ma poi ho deciso per qualche motivo che era un bug del terminale. Per questo mi scuso. Quindi deve essere colpa mia.

Ma non so cosa fare in questo caso. Devo chiamare ObjectDelete e poi ObjectFind e aspettare che fallisca per scoprire se l'oggetto è stato effettivamente rimosso? A giudicare dalla stessa nota, richiede troppo tempo. Non so se una seconda cancellazione funzionerà (nel mio indicatore ho provato a chiamare ObjectDelete due volte di seguito, ma non ha funzionato). E la funzione Sleep negli indicatori non funziona per dare al grafico un po' di tempo per cancellare ogni oggetto. Forse ci sono esempi da qualche parte su come aggirare questo problema?

 
Alexey Viktorov:

Non può succedere che il ciclo duri più a lungo del tempo concesso per eseguire OnDeinit?

Dopo tutto, tutti gli oggetti nel tuo esempio hanno il prefisso "trend", perché non usarlo e rifiutarlo dal ciclo?

Questo è solo nell'esempio. L'indicatore con cui sto lavorando ha nomi complessi. E ho fatto un esempio solo a scopo dimostrativo.

 
Mihail Matkovskij:

Ho certamente pensato a questa nota prima. Ma poi per qualche motivo ho pensato che fosse un bug del terminale. Per questo mi scuso. Si scopre che è colpa mia.

Ma non so cosa fare in questo caso. Devo chiamare ObjectDelete e poi ObjectFind e aspettare che fallisca per scoprire se l'oggetto è stato effettivamente rimosso? A giudicare dalla stessa nota, richiede troppo tempo. Non so se una seconda cancellazione funzionerà (nel mio indicatore ho provato a chiamare ObjectDelete due volte di seguito, ma non ha funzionato). E la funzione Sleep negli indicatori non funziona per dare al grafico un po' di tempo per cancellare ogni oggetto. Forse ci sono esempi da qualche parte su come aggirare questo problema?

Credo che tu stia aggiungendo tutti i puntatori alla lista. Il sottosistema terminale stesso rimuove tali oggetti, i cui puntatori sono nella lista CArrayObj

trend = new CChartObjectTrend();
    if(trend.Create(0, "trend"+(string)i, 0, time[shift], low[shift], time[shift], high[shift]))
      listOfTrendLines.Add(trend);
Qui avete una potenziale perdita di memoria. E una potenziale invocazione di un oggetto non valido.
 
Artyom Trishkin:
Penso che tu aggiunga tutti i puntatori alla lista. Il sottosistema terminale stesso cancella tali oggetti, i cui puntatori sono nella lista CArrayObj

Dopo lo spegnimento del terminale, gli oggetti rimangono sul grafico dopo l'indicatore. E quando riavvio il terminale, questi oggetti sono visibili e rovinano l'intera vista.

 
Mihail Matkovskij:

Dopo lo spegnimento del terminale, gli oggetti rimangono sul grafico dopo l'indicatore. E quando riavvio il terminale, questi oggetti sono visibili e rovinano l'intera vista.

Non sono al mio PC per controllare il tuo esempio. Ho aggiunto al mio post sopra quello che vedo negli errori.