Recent

Author Topic: TStringList.Assign  (Read 1169 times)

egsuh

  • Hero Member
  • *****
  • Posts: 1297
TStringList.Assign
« on: August 29, 2022, 11:58:02 am »
Does it copy objects from source stringlist as well?

For example, let's assume that  ASList and BSList are TStringList variables. And then does the following codes make a new copy of objects or does it just reference to the objects?

Code: Pascal  [Select][+][-]
  1. var
  2.     ASList, BSList: TStringList;
  3.     ti: integer;
  4.     anobj: TMyObject;
  5. begin
  6.  
  7.     for ti := 0 to 100 do begin
  8.          anobj := TMyObject.Create (format('item number %d', [ti]));
  9.          ASList.AddObject (anobj.title, anobj);
  10.     end;
  11.     BSList.Assign(ASList);
  12.  
« Last Edit: August 29, 2022, 11:59:55 am by egsuh »

HeavyUser

  • Sr. Member
  • ****
  • Posts: 397
Re: TStringList.Assign
« Reply #1 on: August 29, 2022, 12:07:02 pm »
Does it copy objects from source stringlist as well?
not the objects no, their references are copied though.

Zvoni

  • Hero Member
  • *****
  • Posts: 2330
Re: TStringList.Assign
« Reply #2 on: August 29, 2022, 12:12:28 pm »
Does it copy objects from source stringlist as well?
not the objects no, their references are copied though.
Which is logical.
Even the "original" StringList doesn't have the Objects themselves, but just references (Pointers) to somewhere in Memory.
Note from doc's: https://www.freepascal.org/docs-html/rtl/classes/tstrings.addobject.html
Quote
Remark:      An object added to the list is not automatically destroyed by the list when the list is destroyed or the string it is associated with is deleted. It is the responsibility of the application to destroy any objects associated with strings.
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

PascalDragon

  • Hero Member
  • *****
  • Posts: 5486
  • Compiler Developer
Re: TStringList.Assign
« Reply #3 on: August 29, 2022, 01:27:43 pm »
Does it copy objects from source stringlist as well?
not the objects no, their references are copied though.
Which is logical.
Even the "original" StringList doesn't have the Objects themselves, but just references (Pointers) to somewhere in Memory.
Note from doc's: https://www.freepascal.org/docs-html/rtl/classes/tstrings.addobject.html
Quote
Remark:      An object added to the list is not automatically destroyed by the list when the list is destroyed or the string it is associated with is deleted. It is the responsibility of the application to destroy any objects associated with strings.

That probably needs to be updated a bit, cause TStringList (in comparison to TStrings) provides a OwnsObjects property since 2010 (so that would be at least since 3.0.0).

Zvoni

  • Hero Member
  • *****
  • Posts: 2330
Re: TStringList.Assign
« Reply #4 on: August 29, 2022, 03:29:20 pm »
That probably needs to be updated a bit, cause TStringList (in comparison to TStrings) provides a OwnsObjects property since 2010 (so that would be at least since 3.0.0).
https://www.freepascal.org/docs-html/rtl/classes/tstringlist.ownsobjects.html
Quote
OwnsObjects can be set to true to let the stringlist instance own the objects in the list: if an element is removed from the list, the associated object (if there is any) will be freed as well. The same is true if the list is cleared or destroyed.
Ouch!!!
How does "Assign" behave in that case?
Does "assign" also set OwnsObject in the Target-List?
What happens if
You create List A. You Assign Strings and Objects to List A. You set OwnsObject of List A to True
You execute ListB.Assign(ListA)
You Free/Destroy ListA --> What happens to the Objects in ListB?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Sieben

  • Sr. Member
  • ****
  • Posts: 310
Re: TStringList.Assign
« Reply #5 on: August 29, 2022, 03:51:57 pm »
Quote
Does "assign" also set OwnsObject in the Target-List?

No. TStringList does not override TStrings.Assign, so Assign doesn't know anything about OwnsObjects.

Quote
What happens if
You create List A. You Assign Strings and Objects to List A. You set OwnsObject of List A to True
You execute ListB.Assign(ListA)
You Free/Destroy ListA --> What happens to the Objects in ListB?

They end up as invalid pointers. So if ListA is to be destroyed before ListB you would set OwnsObjects to True only for ListB, or more general only for the last instance that is supposed to make use of the objects.
Lazarus 2.2.0, FPC 3.2.2, .deb install on Ubuntu Xenial 32 / Gtk2 / Unity7

Thaddy

  • Hero Member
  • *****
  • Posts: 14382
  • Sensorship about opinions does not belong here.
Re: TStringList.Assign
« Reply #6 on: August 29, 2022, 05:32:47 pm »
I don't think that is correct. The TStringlist.OwnsObjects property will be preserved, even after assign from a TSTrings.
TStrings.Assign takes care of the objects property too, but TStringlist.Ownsobjects is preserved after assign from a TStrings.

In this case I mean a Tstrings w/o ownsobjects implementation. Things that are in TStringlist instance that aren't part of Tstrings are preserved.
« Last Edit: August 29, 2022, 05:38:06 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Zvoni

  • Hero Member
  • *****
  • Posts: 2330
Re: TStringList.Assign
« Reply #7 on: August 29, 2022, 05:36:25 pm »
Quote
Does "assign" also set OwnsObject in the Target-List?

No. TStringList does not override TStrings.Assign, so Assign doesn't know anything about OwnsObjects.

Quote
What happens if
You create List A. You Assign Strings and Objects to List A. You set OwnsObject of List A to True
You execute ListB.Assign(ListA)
You Free/Destroy ListA --> What happens to the Objects in ListB?

They end up as invalid pointers. So if ListA is to be destroyed before ListB you would set OwnsObjects to True only for ListB, or more general only for the last instance that is supposed to make use of the objects.
So, in a nutshell: be very careful when using OwnsObjects with Assign
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 14382
  • Sensorship about opinions does not belong here.
Re: TStringList.Assign
« Reply #8 on: August 29, 2022, 05:39:05 pm »
So, in a nutshell: be very careful when using OwnsObjects with Assign
See my answer. It is logical and not complicated.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

ASerge

  • Hero Member
  • *****
  • Posts: 2249
Re: TStringList.Assign
« Reply #9 on: August 29, 2022, 06:56:18 pm »
Let ObjList be a TStringList with OwnsObjects and filled Objects. And let SimpleList be a TStringList without this.

For the ObjList.Assign(SimpleList) all objects in ObjList will be released. After that it is safe to delete both lists in any order.

For the SimpleList.Assign(ObjList) all objects will be copied to the SimpleList, but the OwnsObjects property is not. As a result, it is also possible to delete lists in any order, because SimpleList will not release objects. Care must be taken not to read the SimpleList.Objects when the ObjList already freed.

Zvoni

  • Hero Member
  • *****
  • Posts: 2330
Re: TStringList.Assign
« Reply #10 on: August 29, 2022, 06:59:44 pm »
So, in a nutshell: be very careful when using OwnsObjects with Assign
See my answer. It is logical and not complicated.
Not what i meant.
List A has OwnsObjects=True, you add strings and objects to it.
You execute ListB.Assign(ListA).
It doesn‘t matter if ListB has OwnsObjects true or false.
What happens with the Objects in ListB if you free/clear/destroy List A?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Zvoni

  • Hero Member
  • *****
  • Posts: 2330
Re: TStringList.Assign
« Reply #11 on: August 29, 2022, 07:02:18 pm »
Let ObjList be a TStringList with OwnsObjects and filled Objects. And let SimpleList be a TStringList without this.

For the ObjList.Assign(SimpleList) all objects in ObjList will be released. After that it is safe to delete both lists in any order.

For the SimpleList.Assign(ObjList) all objects will be copied to the SimpleList, but the OwnsObjects property is not. As a result, it is also possible to delete lists in any order, because SimpleList will not release objects. Care must be taken not to read the SimpleList.Objects when the ObjList already freed.
Serge,
Your second example: what happens to the objects in simplelist, when you destroy objlist first?

EDIT: WHOOPS
Just saw that you wrote „care must be taken.“

That‘s actually what i meant above to be careful with that
« Last Edit: August 29, 2022, 07:03:52 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

egsuh

  • Hero Member
  • *****
  • Posts: 1297
Re: TStringList.Assign
« Reply #12 on: August 30, 2022, 02:37:25 am »
I made a simple? program to test this --- My quick conclusion is not to use TStringList.OwnsObject if it has to be used with assign.
You will see a column of four buttons in the lower-right side. There are four actions.

1) created orgStrings, which is a TStringList,
2) Copy it to ValueListEditor.Strings (via Assign),
3) and copy back from ValueListEditor.Strings (via Assign),
4) Free the stringlist (orgStrings).

Currently orgStrings.OwnsObject := False.  If you press down in the order, you will see no problem.

Now, after pressing first and second buttrons, try to add and delete some list by pressing buttons in the low-left side.  You will see the changes in the ValueListeditor.  Then do action 3 and action 4. It's fine.

Now, check the orgStrings OwnsObjects, then you can do :  Actions 1,2, and 4.

But not 1,2,3, and 4 -- there are problem in freeing the object. 

Please advise me on this if I missed anything. What I'm trying to finally is to link objects in the ValueListEditor to the RTTI controls. Currently they are not linked.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5486
  • Compiler Developer
Re: TStringList.Assign
« Reply #13 on: August 30, 2022, 08:59:13 am »
I don't think that is correct. The TStringlist.OwnsObjects property will be preserved, even after assign from a TSTrings.
TStrings.Assign takes care of the objects property too, but TStringlist.Ownsobjects is preserved after assign from a TStrings.

In this case I mean a Tstrings w/o ownsobjects implementation. Things that are in TStringlist instance that aren't part of Tstrings are preserved.

This isn't about the value of the OwnsObjects, but the behaviour when it is set to True: Assign is implemented by TStrings, not TStringList while OwnsObjects is implemented and handled by TStringList. So calling Assign will not change the OwnsObjects property, however if you assign a TStringList with OwnsObjects set to True to a TStrings (any descendant) and then free the original list then all the objects will be freed as well thus leading to invalid references in the Objects property of the destination string list. Same when you assign the contents of a TStrings (again any descendant) to a TStringList with OwnsObjects set to True: if you free the destination list you'll have invalid references in the Objects property of the source list.

So as already said: combining TStringList.OwnsObjects and TStrings.Assign needs to be handled with care.

 

TinyPortal © 2005-2018