Bibliotecas: CDictionary - página 2

 

Descobri um erro no CDictionary. Quando você usa o método Reset, ele exclui o objeto CList em m_data. As chamadas subsequentes para outros métodos que buscam o ponto do dicionário recebem um ponteiro ruim como retorno. Exemplo:


#include "Dictionary.mqh"

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


Eu proporia a seguinte correção para todos os métodos que usam o hash de chave para acessar um objeto CList da matriz 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:

Descobri um erro no CDictionary. Quando você usa o método Reset, ele exclui o objeto CList em m_data. As chamadas subsequentes para outros métodos que buscam o ponto do dicionário recebem um ponteiro ruim como retorno. Exemplo:



Eu proporia a seguinte correção para todos os métodos que usam o hash de chave para acessar um objeto CList da matriz m_data.


Obrigado, Nicoli Shen. Sua solução é a mais "segura". No entanto, não consigo reproduzir o problema.

Outro aspecto que me incomoda está relacionado a isso: um ponteiro de objeto deve poder aceitar um valor nulo. m_data é uma matriz dinâmica, portanto, deve retornar nulo quando um índice não preenchido da matriz for recuperado ou o item armazenado for excluído. O armazenamento de dados de m_data em CList* sem verificação prévia do ponteiro também é feito em outros métodos, como Get() e Delete(), de modo que os scripts de teste acima também devem falhar se esse problema existir. Uma simples atribuição entre um ponteiro e outro pode ser feita sem nenhum erro de acesso ao ponteiro, mesmo que o objeto para o qual o valor l aponta já tenha sido excluído:

#include <Object.mqh>
//+------------------------------------------------------------------+
//| Função de início do programa de script|
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CObject *obj = new CObject();
   delete obj;
   CObject *obj1 = obj; //nenhum erro de acesso a ponteiro inválido
  }
//+------------------------------------------------------------------+

O problema pode ser reduzido ao exemplo acima. Mas, nesse caso, não há erros de ponteiro. Estou curioso porque me lembro de ter encontrado esse mesmo problema em uma compilação anterior, que foi rapidamente corrigida.

No momento, estou usando o MT5 build 1932, mas me avise se estiver faltando alguma coisa.

[Excluído]  

Estou com este erro:


'Key' - token inesperado, provavelmente o tipo está faltando? Dictionary.mqh 39 23

'Key' - função já definida e com tipo diferente Dictionary.mqh 39 23

Veja a declaração de 'CDictionaryEntryBase::Key' Dictionary.mqh 20 22



Tentando cumprir com a compilação 3320

 
Sunfire #:

Estou com este erro:


'Key' - token inesperado, provavelmente o tipo está faltando? Dictionary.mqh 39 23

'Key' - função já definida e com tipo diferente Dictionary.mqh 39 23

Veja a declaração de 'CDictionaryEntryBase::Key' Dictionary.mqh 20 22



Tentando cumprir com a compilação 3320

Tente colocar a palavra-chave "void" antes do método da classe
 
Esse código demonstra uma excelente funcionalidade e aproveita a herança de CObject, permitindo uma integração perfeita com estruturas CArray dentro do dicionário.
 
Para adicionar uma matriz de números inteiros ao dicionário:
#include "Include\Dictionary.mqh"
#include <Arrays\ArrayInt.mqh>
/

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

   CDictionary my_dict;
   
   //--- adicionar arrayint ao dicionário
   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);
  }