How to free objects in stringlist in delphi 7?

delphi

Solution

The original answer below answers the question you asked. However, it transpires in the comments that you are not adding objects to your string list. You are simply adding integers cast to `Pointer`. In that case you must not call `Free` on those integers and that would completely explain your error. So the entire code in your question is gratuitous and you should simply call `Free` on the list when you are done with it.

When you cast an integer to a pointer and add it to the list, there is no memory allocated beyond that used to store the pointer. That is because an integer is a value type. When you add a true pointer or an object then you are adding a `reference` type and disposal of that object involves calling `Free` for an object or `FreeMem` (or `Dispose`) for a pointer.

Original answer to the question as asked

Your original code is correct, albeit a little clunky. The problem you have is in the code that populates `Objects[]`. Since we cannot see that code we can't say what you have got wrong.

Now, having said your code was clunky, here's how I would write it:

procedure ClearList(List: TStringList);
var
  i: Integer;
begin
  for i := 0 to pred(List.Count) do
    List.Objects[i].Free;       
  List.Clear;
end;

Some notes on the above:

- You do not need the `if Assigned(obj)` test before calling `obj.Free`. I explain why not here: Why should I not use "if Assigned()" before using or freeing things?

- There's little point in setting the items to `nil` if you are about to call `Clear`.

- You should not call `List.Free` in such a routine. Your list's life time should be managed separately from the code that clears the list. The call to `List.Free` should be made in the same scope as the call that constructs the list. Or, if this list is a field of a class, then the call to `List.Free` should be made from the destructor of the owning class.

Now, as I have already said in comments to this question and your previous question, all this lifetime management work with the `Objects[]` property of a Delphi 7 string list is very unsatisfactory. It's all too easy to leak objects. I would recommend the following alternatives:

- Switch to using `TObjectList` rather than `TStringList`. Set the `OwnsObjects` property to `True` when you create the list. This will ensure that when an item is deleted from the list, it will be destroyed at the point of removal. You simply hand to the list the responsibility for lifetime management of its items. Note that this will require you to move the `string` that you are storing in your current string list code to be a property of the object. But that is invariably the correct approach anyway so I see that as an upside rather than a drawback.

- If you do wish to keep using a string list, create your own derived class that handles ownership, probably by adding a property named `OwnsObjects`. Push this problem onto the list and let your higher level code be free from that concern. Debug the code once in the context of the list class and then re-use it over and over again safe and secure in the knowledge that it works.

Problem

Below is the thought of Freeing Objects in Delphi's TStrings Items by Zarko Gajic at at About.com.delphi I am using Delphi 7, TStringList does not have OwnsObjects. Running the following code will prompt EaccessViolation error. I donot know why and how to walk around it to free objects. Thanks a lot. ``` procedure TForm6.freelist(const alist: TStringList); var i: integer; begin try for i:=0 to pred(alist.Count) do begin if Assigned(alist.Objects[i]) then begin alist.Objects[i].Free; alist.objects[i]:=nil; end; end; alist.Clear; finally alist.Free; end; end; ``` Edit: I add this line, alist.Objects[i]:=Pointer(0); and there is no error. ... ``` for i:=0 to pred(alist.Count) do begin if Assigned(alist.Objects[i]) then begin alist.Objects[i]:=Pointer(0); //newly added line. alist.Objects[i].Free; alist.objects[i]:=nil; end; end; ... //But I do not know if this is correct and // if the efficiency will be compromised. //This is awkward method? ```

Original source

Related problems