Librerías: CDictionary - página 2

 

He descubierto un bug en CDictionary. Cuando se utiliza el método Reset borra el objeto CList en m_data. Las llamadas posteriores a otros métodos que recuperan el punto del diccionario reciben un puntero malo a cambio. Ejemplo:


#include "Dictionary.mqh"

void OnStart()
{
   CDictionary d;
   d.Set("key", 1);
   d.Reset();
   Print(d.Contains<int>("key"));
}


Yo propondría la siguiente corrección para todos los métodos que utilizan el hash de claves para acceder a un objeto CList desde el array m_data.


template<typename T>
bool CDictionary::Contains(string key)
  {
   bool res=false;
   T value=NULL;
   int index=Index(Hash(key+typename(T)));
   if(CheckPointer(m_data[index]) == POINTER_INVALID)
      m_data[index] = new CList;
   CList *list=m_data[index];
   if(CheckPointer(list))
     {
      CDictionaryEntryBase *model=new CDictionaryEntry<T>(key,value);
      if(CheckPointer(list.Search(model)))
         res=true;
      delete model;
     }
   return res;
  }
 
nicholi shen:

He descubierto un bug en CDictionary. Cuando se utiliza el método Reset borra el objeto CList en m_data. Las llamadas posteriores a otros métodos que recuperan el punto del diccionario reciben un puntero malo a cambio. Ejemplo:



Yo propondría la siguiente corrección para todos los métodos que utilizan el hash de claves para acceder a un objeto CList desde la matriz m_data.


Gracias nicoli shen. Tu solución es la más "segura". Sin embargo, no puedo reproducir el problema.

Otra cosa que me molesta relacionada con esto: un puntero a un objeto debería poder aceptar un valor nulo. m_data es un array dinámico, por lo que debería devolver null cuando se recupera un índice sin rellenar del array, o se borra el elemento almacenado. Almacenar datos de m_data a CList* sin comprobar el puntero de antemano también se hace en otros métodos como Get() y Delete(), por lo que los scripts de prueba anteriores también deberían fallar si existe este problema. Una simple asignación entre un puntero y otro puede realizarse sin ningún error de acceso a puntero, incluso si el objeto al que apunta el lvalue ya ha sido borrado:

#include <Object.mqh>
//+------------------------------------------------------------------+
//| Función de inicio del programa de script|
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CObject *obj = new CObject();
   delete obj;
   CObject *obj1 = obj; //no hay errores de acceso a punteros inválidos
  }
//+------------------------------------------------------------------+

El problema puede reducirse al ejemplo anterior. Pero en este caso, no hay errores de puntero. Tengo curiosidad porque recuerdo haberme encontrado con este mismo problema en una build anterior, que fue rápidamente parcheada.

Actualmente estoy usando MT5 build 1932, pero déjame saber si me estoy perdiendo algo.

[Eliminado]  

Tengo este error


Key' - token inesperado, probablemente falta el tipo Dictionary.mqh 39 23

Key' - función ya definida y de tipo diferente Dictionary.mqh 39 23

ver declaración de 'CDictionaryEntryBase::Key' Dictionary.mqh 20 22



intentando cumplir en build 3320

 
Sunfire #:

Tengo este error:


'Key' - token inesperado, probablemente falta el tipo? Dictionary.mqh 39 23

Key' - función ya definida y de tipo diferente Dictionary.mqh 39 23

ver declaración de 'CDictionaryEntryBase::Key' Dictionary.mqh 20 22



intentando cumplir en build 3320

Prueba a poner la palabra clave "void" antes del método de la clase
 
Este código demuestra una excelente funcionalidad y aprovecha la herencia CObject, permitiendo una integración perfecta con las estructuras CArray dentro del diccionario.
 
Para añadir una matriz entera al diccionario:
#include "Include\Dictionary.mqh"
#include <Arrays\ArrayInt.mqh>
/

//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   CDictionary my_dict;
   
   //--- añadir arrayint al diccionario
   CArrayInt *my_arr_int= new CArrayInt;
   my_arr_int.Add(10);
   my_arr_int.Add(30);
   my_arr_int.Add(45);
   my_dict.Set<CObject*>("arrayint", my_arr_int);
   
   CArrayInt *res_arr;
   res_arr= my_dict.Get<CObject*>("arrayint");
   Print("intarray at 1= ",res_arr.At(1));
//---
   return(INIT_SUCCEEDED);
  }