views:

636

answers:

6
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 is to free this string list's objects?

+5  A: 

You've told the string list that it owns the objects in its Objects array. When that's the case, it will automatically call Free on all those values when you destroy the list, just as your FreeListObjects code does.

But there are no objects there! You have taken Integer values, which are not objects, and type-casted them to force them into a TObject. You can't call Free on an Integer, but at the point that any code calls Free, it doesn't know the original type of the values. When you type-cast, you tell the compilter that you know what you're doing, and the compiler believes you. If you don't really know what you're doing, don't type-cast.

You say you get errors without FreeListObjects, but you should also get errors with FreeListObjects. The problem is that you're calling Free on something that isn't an object. Whether you call it in your own code or you let the library call it shouldn't matter.

You might have spent some time using C#. In that language, integers are automatically "boxed" to be come real objects. That's not how Win32 Delphi works. Delphi doesn't do boxing an unboxing.

Rob Kennedy
+3  A: 

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

But it looks to me like your problem is coming from your example. When I run this, I get access violations because your "objects" you're saving aren't objects at all, they're integers that you've coerced to a TObject slot.

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

Mason Wheeler
+1  A: 

Extending Rob's answer: you trying to free something associated with 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 produce an error).

smok1
This is the best explanation of the error. When you're adding objects to an object-list, they do need to be objects. In WIN32, integers are no objects! (Common mistake for .NET developers with no WIN32 experience.) In Delphi for .NET, this code might actually work!
Workshop Alex
+3  A: 

The problem is because when you set OwnObjects := true, the list will call free to every item inside it. But, since you only are casting your integers to TObject and you aren't really creating an object of type Integer, you are not able to call any method in this casted object.

A solution to your problem would be to create a class like this:

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

and to put in your list items wich are instances of this class, replacing:

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

with

   l.AddObject('', TInteger.Create(code));
eKek0
A: 

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

gabr
A: 

sorry , this my first time in stackoverflow next times i will be more accurate in my questions. i thought that l.addobject will create and add object in tstringlist. Does l.addobject('', tobject(code)) (where l is tstringlist and code is longword) create memory leak or not ? when longword is located ? i can always get code := Longword(L.objects[i]); what object that i am type casting ?

mounir_moussa
The only problem in your question was that it didn't mention what language it was in. Welcome to Stack Overflow. The four (!) people who voted you down were severely overreacting. Anyway, as has already been explained, **there are no objects**. You're not allocating any memory, so there's nothing to leak. Did the documentation for `AddObject` *say* it would allocate a new object? The list stores a *copy* of the value you give it. In your case, the value is an integer, although it *expects* the value to be an object reference. (Note that copying an object reference does *not* copy the object.)
Rob Kennedy