Библиотеки: CDictionary class - страница 2

 

Я обнаружил ошибку в CDictionary. Когда вы используете метод Reset, он удаляет объект CList в m_data. Последующие вызовы других методов, которые получают точку из словаря, получают в ответ плохой указатель. Пример:


#include "Dictionary.mqh"

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


Я бы предложил следующее исправление для всех методов, использующих хэш ключей для доступа к объекту CList из массива 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:

Я обнаружил ошибку в CDictionary. Когда вы используете метод Reset, он удаляет объект CList в m_data. Последующие вызовы других методов, которые получают точку из словаря, получают в ответ плохой указатель. Пример:



Я бы предложил следующее исправление для всех методов, использующих хэш ключей для доступа к объекту CList из массива m_data.


Спасибо, Николи Шен. Ваше решение является "более безопасным". Однако я не могу воспроизвести проблему.

Меня беспокоит еще одна вещь, связанная с этим: указатель на объект должен быть способен принимать нулевое значение. m_data - это динамический массив, поэтому он должен возвращать null, когда из массива извлекается незаполненный индекс или удаляется хранимый элемент. Сохранение данных из m_data в CList* без предварительной проверки указателя происходит и в других методах, таких как Get() и Delete(), поэтому приведенные выше тестовые сценарии также должны завершиться неудачей, если эта проблема существует. Простое присваивание между одним указателем и другим может быть выполнено без каких-либо ошибок доступа к указателю, даже если объект, на который указывает значение lvalue, уже удален:

#include <Object.mqh>
//+------------------------------------------------------------------+
//| Функция запуска программы сценария|
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CObject *obj = new CObject();
   delete obj;
   CObject *obj1 = obj; // нет ошибок доступа к недопустимым указателям
  }
//+------------------------------------------------------------------+

Проблема может быть сведена к приведенному выше примеру. Но в этом случае ошибок с указателями не возникает. Мне интересно, потому что я помню, что столкнулся с этой же проблемой в более ранней сборке, которая была быстро исправлена.

В настоящее время я использую MT5 build 1932, но дайте мне знать, если я что-то упустил.

[Удален]  

У меня такая ошибка:


'Key' - неожиданная лексема, возможно, тип отсутствует? Dictionary.mqh 39 23

'Key' - функция уже определена и имеет другой тип Dictionary.mqh 39 23

см. объявление 'CDictionaryEntryBase::Key' Dictionary.mqh 20 22



пытаюсь установить на билд 3320

 
Sunfire #:

У меня такая ошибка:


'Key' - неожиданный токен, возможно, тип отсутствует? Dictionary.mqh 39 23

'Key' - функция уже определена и имеет другой тип Dictionary.mqh 39 23

см. объявление 'CDictionaryEntryBase::Key' Dictionary.mqh 20 22



пытаюсь установить на билд 3320

Попробуйте поставить ключевое слово "void" перед методом класса
 
Этот код демонстрирует отличную функциональность и использует наследование CObject, что позволяет легко интегрироваться со структурами CArray в словаре.
 
Для добавления целочисленного массива в словарь:
#include "Include\Dictionary.mqh"
#include <Arrays\ArrayInt.mqh>
/

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

   CDictionary my_dict;
   
   //--- добавьте arrayint в словарь
   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);
  }