Erreurs, bugs, questions - page 2794

 
Mihail Matkovskij:

Mon indicateur a commencé à perdre des objets graphiques pour une raison quelconque et ne veut pas les supprimer. J'utilise la suppression automatique dans le destructeur de classe. Je l'appelle :

En conséquence, j'obtiens un faux positif. J'appelle GetLastError() et j'obtiens l'erreur 4101 ("Errory chart identifier"). Supposons. Je compare le chartID de l'objet graphique en cours de suppression avec le résultat de la fonction ChartID() et ils sont exactement les mêmes. Quelle peut être la raison pour laquelle un objet n'est pas supprimé du graphique et comment puis-je contourner ce problème ?

J'ai fait un code source où ce bug se produit :
//+------------------------------------------------------------------+
//|                                           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 pour démontrer le bug.

1. Placez l'indicateur sur le graphique.

2. Retirez l'indicateur du tableau.

3 Appuyez sur Ctrl+B, puis sur le bouton "Lister tout" dans la fenêtre et voyez les objets qui n'ont pas été supprimés.

Objets

J'en ai jusqu'à 294 sur 100000.

Si vous réduisez la valeur du paramètre d'entrée nBars, le bogue n'apparaît pas.

Dossiers :
 

Bon après-midi.

J'ai longtemps hésité à passer de Windows 7 à 10, mais j'ai réinstallé le système cette semaine.

Maintenant j'ai un problème, je ne peux pas télécharger les versions démo de mes indicateurs et autres EAs,

J'ai appuyé sur le bouton de téléchargement et rien ne se passe, je l'ai essayé avec un terminal ouvert et fermé!

J'essaie de le télécharger pour le terminal MT4, je ne suis pas encore passé à MT5.

Mais qu'est-ce qui se passe ?

 
Mihail Matkovskij:
Fait un code source où ce bug se produit :

Que se passe-t-il lorsqu'un pointeur est supprimé ?

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

Existe-t-il une commande permettant de supprimer l'objet graphique ? Voir la note sur ObjectDelete

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

J'en ai jusqu'à 294 sur 100000.

Si nous diminuons la valeur du paramètre d'entrée nBars, le bogue ne se produit pas.

Peut-il arriver que la boucle dure plus longtemps qu'il ne faut pour exécuter OnDeinit ?

Dans votre exemple tous les objets ont le préfixe "trend", pourquoi ne pas l'utiliser et refuser de la boucle ?

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

Que se passe-t-il lorsqu'un pointeur est supprimé ?

Existe-t-il une commande permettant de supprimer l'objet graphique ? Voir la note sur ObjectDelete

J'ai certainement déjà pensé à cette note. Mais ensuite, j'ai décidé pour une raison quelconque que c'était un bug du terminal. Je m'en excuse. Donc ça doit être ma faute.

Mais je ne sais pas quoi faire dans ce cas. Dois-je appeler ObjectDelete, puis ObjectFind et attendre qu'il échoue pour savoir si l'objet a été effectivement supprimé ? A en juger par la même note, cela prend trop de temps. Je ne sais pas si une deuxième suppression fonctionnera (dans mon indicateur, j'ai essayé d'appeler ObjectDelete deux fois de suite, mais cela n'a pas fonctionné). Et la fonction Sleep des indicateurs ne fonctionne pas pour donner au graphique le temps de supprimer chaque objet. Peut-être existe-t-il quelque part des exemples permettant de contourner ce problème ?

 
Alexey Viktorov:

Ne peut-il pas arriver que la boucle dure plus longtemps que le temps imparti pour exécuter OnDeinit ?

Après tout, tous les objets de votre exemple ont le préfixe "trend", pourquoi ne pas l'utiliser et refuser la boucle ?

C'est seulement dans l'exemple. L'indicateur avec lequel je travaille a des noms complexes. Et j'ai donné un exemple juste pour la démonstration.

 
Mihail Matkovskij:

J'ai certainement déjà pensé à cette note. Mais ensuite, pour une raison quelconque, j'ai pensé que c'était un bug du terminal. Je m'en excuse. Il s'avère que c'est ma faute.

Mais je ne sais pas quoi faire dans ce cas. Dois-je appeler ObjectDelete, puis ObjectFind et attendre qu'il échoue pour savoir si l'objet a été effectivement supprimé ? A en juger par la même note, cela prend trop de temps. Je ne sais pas si une deuxième suppression fonctionnera (dans mon indicateur, j'ai essayé d'appeler ObjectDelete deux fois de suite, mais cela n'a pas fonctionné). Et la fonction Sleep des indicateurs ne fonctionne pas pour donner au graphique le temps de supprimer chaque objet. Peut-être existe-t-il quelque part des exemples permettant de contourner ce problème ?

Je pense que vous ajoutez tous les pointeurs à la liste. Le sous-système terminal supprime lui-même ces objets, dont les pointeurs se trouvent dans la liste CArrayObj.

trend = new CChartObjectTrend();
    if(trend.Create(0, "trend"+(string)i, 0, time[shift], low[shift], time[shift], high[shift]))
      listOfTrendLines.Add(trend);
Ici, vous avez une fuite de mémoire potentielle. Et une invocation potentielle d'un objet non valide.
 
Artyom Trishkin:
Je pense que vous ajoutez tous les pointeurs à la liste. Le sous-système terminal supprime lui-même ces objets, dont les pointeurs se trouvent dans la liste CArrayObj.

Après l'arrêt du terminal, les objets restent sur le graphique après l'indicateur. Et lorsque je redémarre le terminal, ces objets sont visibles et gâchent toute la vue.

 
Mihail Matkovskij:

Après l'arrêt du terminal, les objets restent sur le graphique après l'indicateur. Et lorsque je redémarre le terminal, ces objets sont visibles et gâchent toute la vue.

Je ne suis pas à mon PC pour vérifier votre exemple. J'ai ajouté à mon message ci-dessus ce que je vois dans les erreurs.
 
Artyom Trishkin:
Je pense que vous ajoutez tous les pointeurs à la liste. Le sous-système terminal supprime lui-même ces objets, dont les pointeurs se trouvent dans la liste CArrayObj
.

Ici, vous avez une fuite de mémoire potentielle.

S'il y a une fuite de mémoire (par pointeur, l'objet n'a pas été supprimé), le journal indique, à la fin, quels objets n'ont pas été supprimés et combien de mémoire n'a pas été libérée. Mais je n'avais rien de tout ça. Les objets sont supprimés, mais leurs objets graphiques ne sont pas tous supprimés.

Rashid Umarov a remarqué que le problème est que le graphe n'a pas le temps de traiter un si grand nombre de commandes pour supprimer des objets de la liste ! Quel est le rapport avec les fuites de mémoire ?
Документация по MQL5: Основы языка / Типы данных / Указатели объектов
Документация по MQL5: Основы языка / Типы данных / Указатели объектов
  • www.mql5.com
//| Script program start function                                    | //|  Объекты всегда передаются по ссылке                             | //| Передача массива объектов                                        | //| Передача массива указателей на объект                            |
Raison: