Recent

Author Topic: [Solved] How to determine if string list has been allocated  (Read 5290 times)

Joanna

  • Hero Member
  • *****
  • Posts: 1400
[Solved] How to determine if string list has been allocated
« on: November 13, 2023, 07:23:03 am »
I made this object for emulating stacking behavior and it works without needing to be created, however it contains a tstringlist which needs to be created.

It allows me to compile with a "constructor" however this does not get called automatically I must call it.

How do I determine if I need to create the stringlist? it seems to not be nil even if it hasn't been created.

Code: Pascal  [Select][+][-]
  1. TSTRINGSTACK = OBJECT
  2.     STRING_LIST:TStringList;
  3.   PUBLIC
  4.      CONSTRUCTOR CREATE;
  5.      DESTRUCTOR DESTROY; VIRTUAL;
  6.   END;
  7.  
  8. { TSTRINGSTACK }
  9.  
  10.  CONSTRUCTOR TSTRINGSTACK.CREATE; // this is not called automatically
  11.  BEGIN
  12.  if STRING_LIST = nil  // this is false even if stringiest was not created
  13.     then ShowMessage('nil')
  14.     else ShowMessage(STRING_LIST.Count.ToString);   //crashes here
  15.    STRING_LIST:= TStringList.Create;
  16.  END;
  17.  
  18.  DESTRUCTOR TSTRINGSTACK.DESTROY;
  19.  BEGIN
  20.  STRING_LIST.Free;
  21.  END;  
  22.  
« Last Edit: November 14, 2023, 11:42:30 pm by Joanna »

cdbc

  • Hero Member
  • *****
  • Posts: 2462
    • http://www.cdbc.dk
Re: How to determine if string list has been allocated
« Reply #1 on: November 13, 2023, 08:01:09 am »
Hi
In pascal we have <Manual> memory-management, no GC here(sort of)  :D
That means /you/ have to create the objects/classes you use, ...and free them again when you're done.
As yours is an object and as such can be created on the stack, I think it's not initialized to nil, therefore you would have to do this:
Code: Pascal  [Select][+][-]
  1.  CONSTRUCTOR TSTRINGSTACK.CREATE; // this is called manually by you
  2.  BEGIN
  3.     STRING_LIST:= TStringList.Create;
  4.  END;
A constructor gets called (by you) on object begin, so it's safe to assume, that noone created anything before that.
You don't use classes without creating them either do you?!? {hint to your crash above}  ;D
HTH
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6 -> FPC 3.2.2 -> Lazarus 4.0 up until Jan 2025 from then on it's both above &: KDE6/QT6 -> FPC 3.3.1 -> Lazarus 4.99

Joanna

  • Hero Member
  • *****
  • Posts: 1400
Re: How to determine if string list has been allocated
« Reply #2 on: November 13, 2023, 01:23:17 pm »
I thanks for the answer. I’m not sure why it allows the constructor keyword. That is confusing because constructors are usually always called when things are created I thought.

I ended up having to call Create directly but I was hoping for a more robust way to have code that will verify if stringlist exists {and create as necessary } before trying to use it.
As it is now I do not consider it good. I am usually able to check if things that need to be created are nil. I guess this doesn’t work like the classes that I’m used to.

runewalsh

  • Full Member
  • ***
  • Posts: 106
Re: How to determine if string list has been allocated
« Reply #3 on: November 13, 2023, 01:28:27 pm »

gerardus

  • Jr. Member
  • **
  • Posts: 94
Re: How to determine if string list has been allocated
« Reply #4 on: November 13, 2023, 04:26:37 pm »
I thanks for the answer. I’m not sure why it allows the constructor keyword. That is confusing because constructors are usually always called when things are created I thought.

I ended up having to call Create directly but I was hoping for a more robust way to have code that will verify if stringlist exists {and create as necessary } before trying to use it.
As it is now I do not consider it good. I am usually able to check if things that need to be created are nil. I guess this doesn’t work like the classes that I’m used to.

Things always need to be created.
When you create a TSTRINGSTACK  object the STRING_LIST object is not allocated, so there is no need to check and you need to create it to use it.
If what you want to do is some kind of lazy initialization, you should set STRING_LIST :=nil when creating the TSTRINGSTACK object and then use a getter method wich will initialize STRING_LIST if nil and then return it.


Code: Pascal  [Select][+][-]
  1. TSTRINGSTACK = OBJECT
  2.   private
  3.     STRING_LIST:TStringList;
  4.    function  GetStringList: TStringList;
  5.   PUBLIC
  6.      CONSTRUCTOR CREATE;
  7.      DESTRUCTOR DESTROY; VIRTUAL;
  8.      property StringList: TStringList read GetStringList;
  9.   END;
  10.  
  11. { TSTRINGSTACK }
  12.  
  13.  CONSTRUCTOR TSTRINGSTACK.CREATE;
  14.  BEGIN
  15.     STRING_LIST := nil
  16.  END;
  17.  
  18.  DESTRUCTOR TSTRINGSTACK.DESTROY;
  19.  BEGIN
  20.   if STRING_LIST<>nil then
  21.     STRING_LIST.Free;
  22.  END;  
  23.  
  24. function  TSTRINGSTACK.GetStringList: TStringList;
  25. begin
  26.   if STRING_LIST=nil then
  27.     STRING_LIST:= TStringList.Create;
  28.   Result := STRING_LIST:
  29. end;
  30.  
« Last Edit: November 13, 2023, 04:32:00 pm by gerardus »

rvk

  • Hero Member
  • *****
  • Posts: 6885
Re: How to determine if string list has been allocated
« Reply #5 on: November 13, 2023, 04:35:25 pm »
I thanks for the answer. I’m not sure why it allows the constructor keyword. That is confusing because constructors are usually always called when things are created I thought.
So, please show us how you use the code from your opening post.
How do you create the object ???

I ended up having to call Create directly but I was hoping for a more robust way to have code that will verify if stringlist exists {and create as necessary } before trying to use it.
There are ways to do this.
You could even make a class function which creates its own object/self.

But you need to show us what exactly you want (with an example of how you want to use it).

PS. You SHOULD call the constructor Create to create an object.
The Constructor keyword defines a constructor procedure Name for a class.
 
Quote
When creating an object, you call a Constructor method of the class, not the object:
 objectName := ClassName.Create(parms);
The Name for the constructor is normally Create, but is not restricted to this. It is very wise to keep to this name.
https://www.delphibasics.co.uk/RTL.php?Name=Constructor

For example... for a TStringList you also call .Create to create the StringList.
So I'm not sure what it is exactly what you want and meant.
« Last Edit: November 13, 2023, 04:38:16 pm by rvk »

cdbc

  • Hero Member
  • *****
  • Posts: 2462
    • http://www.cdbc.dk
Re: How to determine if string list has been allocated
« Reply #6 on: November 13, 2023, 06:20:32 pm »
Hi
In the old TP-5.5 days it used to go like this:
Code: Pascal  [Select][+][-]
  1. type
  2.   { TTest }
  3.   PTest = ^TTest; // the fore-runner for our classes today :o)
  4.   TTest = object
  5.     mol: integer;
  6.     constructor Init;
  7.     function WriteMeaningOfLife: integer;
  8.     destructor Done;
  9.   end;
  10.  
  11. { TTest }
  12. constructor TTest.Init;
  13. begin
  14.   mol:= 42;
  15. end;
  16.  
  17. function TTest.WriteMeaningOfLife: integer;
  18. begin
  19.   writeln('The Meaning of Life = ',mol);
  20.   Result:= mol;
  21. end;
  22.  
  23. destructor TTest.Done;
  24. begin
  25.   mol:= 0;
  26. end;
  27. ///// and to test it I just stuffed it into an event-handler /////
  28. procedure TfrmTestObs.btnAvailableClick(Sender: TObject);
  29. var o: PTest; t: TTest;
  30. begin
  31.   showmessage('T = '+t.WriteMeaningOfLife.ToString);
  32.   o:= new(PTest,Init); // extende new-syntaks
  33.   showmessage('O = '+o^.WriteMeaningOfLife.ToString);
  34.   dispose(o,Done); // extended dispose-syntaks
  35. end;  
  36.  
As you can see, it all makes perfect sense  ;)
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6 -> FPC 3.2.2 -> Lazarus 4.0 up until Jan 2025 from then on it's both above &: KDE6/QT6 -> FPC 3.3.1 -> Lazarus 4.99

Joanna

  • Hero Member
  • *****
  • Posts: 1400
Re: How to determine if string list has been allocated
« Reply #7 on: November 14, 2023, 12:46:20 am »
The main problem I guess is that the constructor is not being called automatically. There seems to be no way for the object to initialize itself. It is used like this
Code: Pascal  [Select][+][-]
  1. Tmygrid = class(tdbgrid)
  2. Constructor create(theowner:tcomponet);
  3. Var Sortstrings:tstringstack;
  4.  
The object is created when the tmydbg class is created .
The string stack is used to record names of columns as they are sorted With most recent sort column at front of list.

Yes I know I could initialize the object containing stringlist from the class constructor but isn’t there a better way? I want the object to automatically create and free the stringlist or at least be able to determine if stringlist was created.

I am currently testing the object by itself without the class.
Do I have to use advanced records to do this?
« Last Edit: November 14, 2023, 12:49:45 am by Joanna »

jamie

  • Hero Member
  • *****
  • Posts: 7300
Re: How to determine if string list has been allocated
« Reply #8 on: November 14, 2023, 01:27:33 am »
Instead of making a dynamic object within a Class define, use a static object.

Create the object and its functions outside of the class of course and then use that object as a variable define within the class.

 When the class is constructed the memory that your object is occupying will be zeroed out. This means any items within that object will all be zeroed or NIL, this would include your StringList, too that lives within the object and its living within the class.

 By simply testing for NIL, you can determine if the String List is valid and thus create a method to add to the list that would first test for a NIL and then create the list.

So, to reiterate in short if you use a fixed object instead of constructing it via NEW etc., the object's memory will be zeroed because it is using the classes instance memory which gets zeroed.

The only true wisdom is knowing you know nothing

rvk

  • Hero Member
  • *****
  • Posts: 6885
Re: How to determine if string list has been allocated
« Reply #9 on: November 14, 2023, 06:20:29 am »
Yes I know I could initialize the object containing stringlist from the class constructor but isn’t there a better way?
NO. There isn't.
That's how you do it on Object Pascal.

Joanna

  • Hero Member
  • *****
  • Posts: 1400
Re: How to determine if string list has been allocated
« Reply #10 on: November 14, 2023, 11:56:42 am »
Jamie do you have any code to illustrate just to see if I understand you correctly?
 I’m currently using the object without creating it . But I still have to create stringlist.

rvk

  • Hero Member
  • *****
  • Posts: 6885
Re: How to determine if string list has been allocated
« Reply #11 on: November 14, 2023, 11:58:29 am »
I’m currently using the object without creating it . But I still have to create stringlist.
Can you show valid code where you use TSTRINGSTACK without creating it??


Joanna

  • Hero Member
  • *****
  • Posts: 1400
Re: How to determine if string list has been allocated
« Reply #12 on: November 14, 2023, 12:32:22 pm »
Code: Pascal  [Select][+][-]
  1.  
  2.  
  3. Tmygrid = class(tdbgrid)
  4. Constructor create(theowner:tcomponet);
  5. Var Sortstrings:tstringstack;
  6. End;
  7.  
  8. Constructor tmygrid. create(theowner:tcomponet);
  9. Begin
  10.  Sortstrings.init;
  11. End
  12.  

MarkMLl

  • Hero Member
  • *****
  • Posts: 8504
Re: How to determine if string list has been allocated
« Reply #13 on: November 14, 2023, 12:40:50 pm »
I'm very uncomfortable getting involved with this- for lots of reasons- but I'm not sure that anybody has yet pointed out explicitly that tstringstack is declared as an object rather than a class.

So, if my understanding is correct, it will be allocated on the stack (rather than the heap) while that constructor is running, but will go out of scope as soon as the constructor is exited.

Behaviour after that point is undefined, but probably not what was intended.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

rvk

  • Hero Member
  • *****
  • Posts: 6885
Re: How to determine if string list has been allocated
« Reply #14 on: November 14, 2023, 12:47:42 pm »
Code: Pascal  [Select][+][-]
  1.  
  2. Constructor tmygrid. create(theowner:tcomponet);
  3. Begin
  4.  Sortstrings.init;
  5. End
  6.  

There is no .Init constructor in your TStringStack. At least not in the code you showed.
Do you mean that to be: Sortstrings.Create; ?????
Then you are initializing the SortStrings there.
When doing that... the STRING_LIST isn't created yet and you can do that in the constructor (as shown in the second post).

So you ARE calling the constructor !!

PS. You are mixing old style Objects with new style classes here in your code.
Is that a good idea ??


 

TinyPortal © 2005-2018