-2

I am using delphi XE5. This a resume of my code, Next code works, but there have to be something in my code that destroy normal behaviour:

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.

And now another unit:

 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. 

That is a resume of my code, I can put all my code because is too big, but I would like to know where I can search to resolve this problem. I am not is not easy, maybe I am not the only one with that problema, maybe some class in the uses, class variables, there is something that causes a memory problema in that dictionary, but no way to find it.

Max1298492
  • 91
  • 3
  • 8
  • 2
    The code shown here does not seem to have the described error. Make it compile and see if you are missing an important code piece. – mjn Oct 18 '14 at 13:28
  • Please post real code that shows the problem, this will never compile – Sir Rufo Oct 18 '14 at 18:35

1 Answers1

1

It's a little hard to be sure of the problem because you posted code that does not compile. For future reference, please don't do that. It's good to cut down the code to a small size, but you should then make it into a small console application that compiles and runs and demonstrates the fault. In spite of this, I think that I can see where the problem is.

You are creating objects and then adding them to a string list with

TS.AddObject(...);

But then you never free those objects. That, I guess, is the source of the leak. You can deal with this by setting the OwnsObjects property of the string list to True.

Specifies whether the string list owns the objects it contains.

The OwnsObjects property specifies whether the string list owns the stored objects or not. If the OwnsObjects property is set to True, then the Destroy destructor will free up the memory allocated for those objects.

That I think will explain the leaks. The other part of your question is why index 0 contains the item that you added second. The only explanation for that, given the code in the question, is that your string list has the Sorted property set to True.

Again, I'm inferring this with a little intuition, but if you have only posted a complete program that compiled and run then your question could have been answered with complete certainty.


I do wonder whether or not a string list is the correct class to be using here. Perhaps you would be better with TObjectDictionary<string, TClass1>. You would create it like this:

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

The use of doOwnsValues tells the dictionary that it is take assume ownership of the objects that you add as values and destroy them when they are removed from the dictionary, or when the dictionary is destroyed.

Note also that your insertValue method can be implemented in a far simpler way using the AddOrSetValue method.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I endorse using TDictionary. Based on what I have tried, it is much, much faster than using a TStringList for the same thing. – Ron Maupin Oct 18 '14 at 13:26