Jump to content
AlanScottAgain

Do I need to free list

Recommended Posts

Hi

I have an object that holds a TObjectList.

 

I have a helper class that builds The objects that go into the TObjectList.

Currently I just Assign the helper ObjectList to the RootObjectList.

 

 RootObject.ObjectsList := Helper.DrawingObjectsList;

 

I was wondering if I should Free the RootObjectList - if it has objects - before I assign the new list?

 

Otherwise what happens to the old possibly orphaned list? Does the compilers take care of it?
I have OwnsObjects set to True.

 

Thanks

Alan

Share this post


Link to post

If a TObjectList<T> has OwnsObjects = True, it will free the contained objects when the list itself is freed.

If no one ever frees the list, it will stay in memory, and all its contained objects.

 

You say you produce a new list. If no one else keeps a reference to the old list anymore, it should be freed.

 

Even better, in my opinion, would be not creating new lists all the time, but that you change your helper object so that you pass your already existing list, and it will add the new object to that list, instead of creating its own.

This way, you don't have to deal with creating and freeing lists, you just have one single list of the entire lifetime of your outer object.

Edited by Der schöne Günther

Share this post


Link to post
7 hours ago, AlanScottAgain said:

Hi

I have an object that holds a TObjectList.

 

I have a helper class that builds The objects that go into the TObjectList.

Currently I just Assign the helper ObjectList to the RootObjectList.

 

 RootObject.ObjectsList := Helper.DrawingObjectsList;

 

I was wondering if I should Free the RootObjectList - if it has objects - before I assign the new list?

 

Otherwise what happens to the old possibly orphaned list? Does the compilers take care of it?
I have OwnsObjects set to True.

 

Thanks

Alan

Object references are not automatically managed by the compiler-generated code, unlike interface references. So your code has a couple of possible problems re lifetime control:

  • If the assignment just replaces the RootObject.Objectlist (the internal reference held by RootObject) you leak the old object list's memory, as well as the objects held by the old list. After the assignment you now have two object list references referring to the same objectlist instance, one in RootObject.Objectlist, the other in Helper.DrawingObjectlist. If you free one the other becomes invalid and will cause an AV when next accessed.
  • If the assignment resolves to a call to a setter method (i.e. RootObject.Objectlist is a property with a setter method) and the setter frees the old reference before storing the one passed in you do not leak memory for the old list, but you still have two references to the same object list, with the problems mentioned above.
  • If the assignment resolves (via setter method) to clearing the content of the internal list first (assuming OwnsObject = true, so the contained objects are freed) and then storing the content of the passed list into the internal list you don't have the two problems mentioned in the first bullet point, but you have another: you now have two lists holding references to the same objects. Free an object in one list and the reference in the other becomes invalid. Especially fun if both lists have OwnsObjects set to true.
  • If the assignment resolves (via setter method) to clearing the content of the internal list first (assuming OwnsObject = true, so the contained objects are freed) and then moving the content of the passed-in list to the internal one you don't have a memory management problem, but the source list is now empty after the assignment. That may not be acceptible, depending on your requirements.

There are two ways out of this mess:

  1. Change the design from using object references to using interface references. This gives you automatic lifetime control of the objects behind the interfaces via reference counting.
  2. Implement a deep copy mechanism for the objects held in the lists. The assignment would then clear the old content of the list and then store copies (clones) of the objects in the source list into the internal list. This way the two lists are completely independent of each other, changing objects in one has no effect on the objects in the other. Both lists can have OwnsObject = true and there will be no memory leaks.

 

Edited by PeterBelow

Share this post


Link to post

Thanks for both for the answers.

I had a feeling I was getting into trouble.

 

I like the idea of passing the list to the helper object - its simple.

Even though I have dabbled in Delphi for a long time I really don't understand interfaces. But it's a good time to learn.

Once again thanks.

Alan

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×