-2

我正在使用德尔福 XE5。这是我的代码的简历,下一个代码有效,但我的代码中必须有一些东西会破坏正常行为:

unit Class1;
type
 TClass1 = class
  private 
    FDic:TDictionary<String,String>.Create;
  public
constructor create;
    procedure insertValue(key,value:String);
  end;

 implementation
 constructor TClass1.create;
 begin
   FDic:=TDictionary<String,String>.Create;
 end;
 procedure insertValue(key,value:String);
 begin
  if(FDic.ContainsKey(key))then
      FDic[key] := value
  else
  begin
    FDic.Add(key,value);
  end;
end.

现在另一个单位:

 unit Class2;
 type
  uses Class2;
  TClass1 = class
   public
     class2 :TClass2;
     TS: TStringList;
     procedure DoSomething;
   end;

   implementation

   procedure TClass1.DoSomething;
   var 
   i: Integer;
    c,test: TClass1;
   begin

    c := TClass1.create;
        c.insertValue('height','.34cm');
    c.insertValue('width','22cm');
    c.insertValue('radio','2cm');
        TS.AddObject('square',c);
        c := TClass1.create;
        c.insertValue('height','.88cm');
    c.insertValue('width','11cm');
    c.insertValue('top','12cm');
        TS.AddObject('circle',c);

         test := TS.Objects[0] as TClass1;//test.FDic height should be .34cm but gets the value of the last object create, the same for width an common keys.

   //here when I look for the values of FDic test.FDic.Items['height'] the value is .88cm instead of .34cm, each time the values of any element of the Dictionary is replace with the previous of the last object created. And the memory address is the same. Why don't create a new memory address for any new element if it is a different object. 

那是我的代码简历,我可以放我所有的代码,因为太大了,但我想知道我可以在哪里搜索来解决这个问题。我不是不容易,也许我不是唯一一个有这个问题的人,也许是使用中的某个类,类变量,有一些东西会导致该字典中出现内存问题,但无法找到它。

4

1 回答 1

1

确定问题有点困难,因为您发布的代码无法编译。为了将来参考,请不要这样做。将代码缩减到很小的大小是好的,但是您应该将其制成一个小型控制台应用程序,该应用程序可以编译和运行并演示错误。尽管如此,我认为我可以看到问题出在哪里。

您正在创建对象,然后将它们添加到字符串列表中

TS.AddObject(...);

但是你永远不会释放这些对象。我想,这就是泄漏的根源。您可以通过将OwnsObjects字符串列表的属性设置为 来解决此问题True

指定字符串列表是否拥有它包含的对象。

OwnsObjects属性指定字符串列表是否拥有存储的对象。如果OwnsObjects属性设置为True,则Destroy析构函数将释放为这些对象分配的内存。

我认为这将解释泄漏。您问题的另一部分是为什么索引 0 包含您第二次添加的项目。鉴于问题中的代码,对此的唯一解释是您的字符串列表的Sorted属性设置为True.

再一次,我用一点直觉来推断这一点,但如果你只发布了一个完整的编译和运行的程序,那么你的问题可能已经得到了完全肯定的回答。


我确实想知道字符串列表是否是在这里使用的正确类。也许你会更好TObjectDictionary<string, TClass1>。你会像这样创建它:

dict := TObjectDictionary<string, TClass1>.Create([doOwnsValues]);

的使用doOwnsValues告诉字典它假定您作为值添加的对象的所有权,并在它们从字典中删除或字典被销毁时销毁它们。

另请注意,您的insertValue方法可以使用该AddOrSetValue方法以更简单的方式实现。

于 2014-10-18T13:10:46.217 回答