ライブラリ: CDictionary - ページ 2

 

CDictionaryのバグを発見しました。リセット・メソッドを使用すると、m_data内のCListオブジェクトが 削除されます。その後、辞書からポイントを取得する他のメソッドを呼び出すと、不正なポインタが返されます。例


#include "Dictionary.mqh"

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


キー・ハッシュを使用して m_data 配列から CList オブジェクトにアクセスするすべてのメソッドについて、以下の修正を提案します。


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のバグを発見しました。リセット・メソッドを使用すると、m_data内のCListオブジェクトが削除されます。その後、辞書からポイントを取得する他のメソッドを呼び出すと、不正なポインタが返されます。例



キー・ハッシュを使用してm_data配列からCListオブジェクトにアクセスするすべてのメソッドに対して、以下の修正を提案します。


nicoli shenさん、ありがとうございます。あなたの解決策は「より安全な」ものです。しかし、私はこの問題を再現できません。

m_dataは動的な配列なので、配列から未入力のインデックスが取り出されたときや、格納されている項目が削除されたときにnullを返すべきです。事前にポインタをチェック せずにm_dataからCList*にデータを格納することは、Get()やDelete()のような他のメソッドでも行われるので、この問題が存在する場合、上記のテストスクリプトも失敗するはずです。あるポインタと別のポインタとの間の単純な代入は、l値が指すオブジェクトがすでに削除されていても、ポインタ・アクセス・エラーなしで実行できます:

#include <Object.mqh>
//+------------------------------------------------------------------+
//| スクリプト・プログラム開始機能|
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CObject *obj = new CObject();
   delete obj;
   CObject *obj1 = obj; //無効なポインタ・アクセス・エラーはない
  }
//+------------------------------------------------------------------+

この問題は、上の例のように減らすことができます。しかしこの場合、ポインタ・エラーは発生しません。以前のビルドでこれと同じ問題に遭遇した覚えがあり、すぐにパッチが適用されたので不思議に思っています。

私は現在 MT5 ビルド 1932 を使用していますが、何か見落としていることがあれば教えてください。

削除済み  

このようなエラーが発生します:


'Key' - 予期しないトークンです。おそらく型が不足しているのでしょう。 Dictionary.mqh 39 23

'Key' - 関数はすでに定義されており、型が異なります Dictionary.mqh 39 23

CDictionaryEntryBase::Key' の宣言を参照 Dictionary.mqh 20 22



ビルド3320での試行錯誤

 
Sunfire #:

このようなエラーがあります:


'Key' - unexpected token, probably type is missing? 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);
  }