Recent

Author Topic: TStringList Question  (Read 2064 times)

JLWest

  • Hero Member
  • *****
  • Posts: 1054
TStringList Question
« on: October 12, 2021, 08:42:50 pm »
Am I right in assuming that a TStringList when created is a global item. That is if created in a procedure or function other function or procedures have viability to the 
TSringList created.

And why would you use TList.Free instead of TList.Destroy; I understand  Destroy.  Destroy clears the TStringList, release all memory allocated for the storage of the strings, and then calls the inherited destroy method.

So why have TStringList.Free
 


Code: Pascal  [Select][+][-]
  1. TList : TstringList.Create
  2.  Try
  3.   Some Code
  4.  finally
  5.   TList.Free;
  6.      or
  7.   TList.Destroy;
  8.  
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

jamie

  • Hero Member
  • *****
  • Posts: 4928
Re: TStringList Question
« Reply #1 on: October 12, 2021, 09:24:29 pm »
objects/classes what ever need to be cleaned up if they are locally created unless  you are returning their newly creation from the function. And creating them locally in a procedure does not make them global unless of course you return that object pointer to something outside the procedure, then it can be used elsewhere.

  And for free over destroy, Free first test to insure the object isn't NIL already and if is it aborts and does nothing.
 

 Calling destroy directly will not first test this and then you get a nice ester egg.

 If you use FreeAndNil that does both, it first test for a NIl, calls Destroy if valid and then sets the object to Nil.

 This way if only Free is used somewhere it will cleanly exit without problems.
The only true wisdom is knowing you know nothing

MarkMLl

  • Hero Member
  • *****
  • Posts: 3270
Re: TStringList Question
« Reply #2 on: October 12, 2021, 09:53:35 pm »
I held off commenting because I wasn't confident on the Free/Destroy aspect, but to extend what Jamie said:

The storage associated with TStringList is on the heap, so it is /potentially/ accessible and needs to be freed at some appropriate point (i.e. it's neither garbage-collected nor reference counted). However the variable into which the (automatically-dereferenced) pointer to the TStringList is placed is subject to the normal scoping rules, i.e. if it's local then you lose your way of accessing the object when the current procedure is exited.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1008
    • Lebeau Software
Re: TStringList Question
« Reply #3 on: October 12, 2021, 10:09:01 pm »
Am I right in assuming that a TStringList when created is a global item.

No.  If you want it to be global, you have to declare it in a global scope.

That is if created in a procedure or function other function or procedures have viability to the 
TSringList created.

No.  You would have to assign it to a global variable, or otherwise pass it around.

And why would you use TList.Free instead of TList.Destroy;

Free() checks if an object's Self pointer is not nil before calling Destroy() on it.

In a local scenario, where you Create() and Destroy() an object in the same procedure, this extra check is typically redundant, but harmless.  You can call Destroy() directly, if you want to.

Where Free() really comes in handy is when an object is created as a member of another object.  Whether the member object is created or not in the parent object's constructor, or assigned externally after construction, the parent's destructor can freely destroy the member object using Free().  An object's members are zeroed out before its constructor is entered.  If a constructor raises an uncaught exception, the destructor is still called.  So, if a constructor/assignment fails with an exception before the member is set, that member will be nil in the parent's destructor.  Calling Free() on that member will work fine, but calling Destroy() on it will not.
« Last Edit: October 12, 2021, 10:18:05 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

PascalDragon

  • Hero Member
  • *****
  • Posts: 3412
  • Compiler Developer
Re: TStringList Question
« Reply #4 on: October 13, 2021, 09:38:28 am »
Am I right in assuming that a TStringList when created is a global item.

No.  If you want it to be global, you have to declare it in a global scope.

Well, to be fair, one could say that the created instance itself is global and its only the reference to it that is local, because when a routine is left without freeing the instance the instance itself continues on (aka memory leak if there's no other reference to it) while the reference to it gets lost.

JLWest

  • Hero Member
  • *****
  • Posts: 1054
Re: TStringList Question
« Reply #5 on: October 13, 2021, 05:11:47 pm »
Thanks all.

Not sure if i understand how to declare a tstringlist so it is global.

Maybe:

 
Code: Pascal  [Select][+][-]
  1. private
  2.   public
  3.   end;
  4. Const
  5. Var
  6. TList : TStringlist;
  7. implementation  
  8.  procedure TForm1.FormCreate(Sender: TObject);
  9.   begin                        
  10.    TList := TstringList.Create;
  11.  end;
       
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

Bart

  • Hero Member
  • *****
  • Posts: 4477
    • Bart en Mariska's Webstek
Re: TStringList Question
« Reply #6 on: October 13, 2021, 05:40:11 pm »
Do you need access to that list outside methods of your form?
If so, can you supply it as a parameter to functions/procedures outside the scope of the form?

In other words: why does it need to be a global variable?

Bart

MarkMLl

  • Hero Member
  • *****
  • Posts: 3270
Re: TStringList Question
« Reply #7 on: October 13, 2021, 06:51:22 pm »
Code: Pascal  [Select][+][-]
  1. var
  2.   TList : TStringlist;
  3.  

Definitely not that: a leading T is a convention indicating that the entry being defined is a type... and since there is in fact a TList at the system level you'd be open to all sorts of confusion.

While a global variable would work, in general they're deprecated /except/ for forms where they're a necessary evil however see this:

Code: Pascal  [Select][+][-]
  1. ...Form definition stuff
  2. private
  3.   public
  4. end;
  5.  

That public section is where you put stuff that you want to be visible.

Otherwise, as Bart has said, pass it as a parameter.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

JLWest

  • Hero Member
  • *****
  • Posts: 1054
Re: TStringList Question
« Reply #8 on: October 14, 2021, 12:37:08 am »
@Bart

It doesn't need to be global. I use it now as a local var and pass it to a procedure. The reason for my question is:

What if you were using a TStringList with a large amount of data, say 50,000 strings of 150 characters each. Seems if it was a global you wouldn't be passing a large amount of data around.

So I was wondering how you would declare it.
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

PascalDragon

  • Hero Member
  • *****
  • Posts: 3412
  • Compiler Developer
Re: TStringList Question
« Reply #9 on: October 14, 2021, 09:10:26 am »
What if you were using a TStringList with a large amount of data, say 50,000 strings of 150 characters each. Seems if it was a global you wouldn't be passing a large amount of data around.

With classes you aren't passing huge amount of data around. When you create a class instance it's a memory block in the heap and all your variable is is a reference to that memory block. If you now pass that variable around functions, procedures and methods all you pass around is the reference which has a size of SizeOf(Pointer), the memory block stays where it is. This is a difference to records and TP-style objects which - if not explicitly declared as a pointer type - are allocated on the stack and thus their data is copied each time they're passed around (except if you're using var, out or constref parameters).

 

TinyPortal © 2005-2018