Error in free TStringList object

procedure FreeListObjects( l : TStrings);
var i : integer;
BEGIN
   FOR i :=  0 TO l.Count -1 DO BEGIN
       l.Objects[i].Free;
       l.Objects[i] := NIL;
   END;
end;



PROCEDURE StringListAdd;
VAR i : INTEGER; Code : LONGWORD;
BEGIN
   l := Classes.TstringLIST.CREATE;
   FOR i := 0 TO 4 DO BEGIN
       Code := i  ;
       l.AddObject('', TObject(code));
   END;
   Code := LONGWORD(l.Objects[2]);
   FreeListObjects(l);
   l.Free;
END;

      

When I use l.OwnsObjects := TRUE

without FreeListObjects(l)

, an error occurs.

Who should free these string list objects?

+2


source to share


7 replies


You told the list of strings that it owns the objects in the array Objects

. In this case, it will automatically call Free

for all these values ​​when the list is destroyed, as your code does FreeListObjects

.

But there are no objects there! You have taken values Integer

that are not objects and typecast them to force them into TObject

. You can't call Free

on Integer

, but at the point where any code calls Free

, it doesn't know the original type of the values. When you type, you tell the compiler that you know what you are doing, and the compiler believes you. If you really don't know what you are doing, do not type.



You say you get errors without FreeListObjects

, but you should also get errors with FreeListObjects

. The problem is that you are calling Free

on something that is not an object. If you call it in your own code, or if you let the library call it, it doesn't matter.

You may have spent some time using C #. In this language, integers are automatically "boxed" to be real objects. This is not how Win32 Delphi works. Delphi does not box for unpacking.

+7


source


OwnsObjects does basically the same thing as your FreeObjects procedure, but it handles it internally when the StringList itself is freed.

But it seems to me that your problem is coming from your example. When I run this, I get access violations because your "objects" you are storing are not objects, they are integers that you coerce the TObject word.



It's just a guess, but are you just learning Delphi, after a background in some other language where "everything is an object"? This is not the case in Delphi. Objects are one data type out of many, and you cannot call Free on other data types.

+3


source


The problem is that when you set OwnObjects: = true, the list will be called for free for every item inside it. But, since you are only casting your integers into the TObject and you are not actually creating an Integer object, you cannot call any method on that cast object.

The solution to your problem is to create a class like this:

TInteger = class
  value: integer;
  constructor Create(v: integer);
end;

      

and put in the list the elements that are instances of this class, replacing:

   l.AddObject('', TObject(code));

      

from

   l.AddObject('', TInteger.Create(code));

      

+3


source


Expanding on Rob's answer: you are trying to free something related to addresses: nil, 0x00000001, 0x00000002, 0x00000003, and 0x00000004 respectively. Since there are no valid objects there, there will be an access violation (note: calling Free on nil object does not result in an error).

+2


source


Other people have already pointed out the problem in your code, so I'll just add one piece of information. If you just want to store integers in a list, use TGpIntegerList or TGpInt64List from my GpLists . Free, unlimited.

0


source


Sorry, this is my first time on stackoverflow, next time I will be more precise in my questions. I thought l.addobject would create and add the object to the tstringlist. Does l.addobject ('', tobject (code)) (where l is tstringlist and code is longword) leak memory or not? when is the slogan found? I can always get the code: = Longword (L.objects [i]); what object am I licking in type?

0


source


I know that in Delphi you need to free every object by following these steps.

if your objects are of the following class eg.

TheClass = Class(TObject)
public
thestr:String;
end;

      

Then this is how you would do it:

procedure FreeListObjects( l : TStrings);
var i : integer;
BEGIN
   FOR i :=  0 TO l.Count -1 DO BEGIN
       TheClass(l.Objects[i]).Free;   <----
       l.Objects[i] := NIL;
   END;
end;

      

Each object in the TStrings list is actually in its own memory, even if you deallocate the pointer to your objects. You have to free the memory of objects by doing the above. This is how I do it and did it in Delphi. He always worked for me.

0


source







All Articles