Recent

Author Topic: {SOVED} how to check to see if TStringList has been created?  (Read 19823 times)

userx-bw

  • Full Member
  • ***
  • Posts: 178
{SOVED} how to check to see if TStringList has been created?
« on: February 13, 2014, 04:20:45 am »
If one declares a TStringList

Code: [Select]
ImageList : TStringList;

.....

 Form1.ImageList := FindAllFiles(ExtractFilePath(Form1.ImageFile), '*.*', false);

  Form1.ImageList.Sort; 
...


the TStringList creates itself so How do I check to see it is has been created ?

this seems to work but please enplane to me what does NIL mean, Because I did not set my directory to create the TStingList then I clicked the button to call a function to use the ImageList (TStringList) that I never set, and I got this message, but I read that you have to set the TStringList to nil after you create it. I just want to be sure this is the proper code that does check to see that the List has not been created and catch the error to handle it.

Code: [Select]
if Form1.ImageList = nil then
     if MessageDlg('OOPS!', ' you forgot to set the Directory',
     mtError, [mbAbort], 0 ) = mrAbort
        then abort; 

Thanks...
« Last Edit: February 14, 2014, 01:43:04 am by userx-bw »
My Finished Projects
https://sourceforge.net/projects/mhsetroot/
https://sourceforge.net/projects/gmhsetrootfreepascalfrontend/

HP Elitetbook 6930p Dual Core Intel vPro 2.66 gHz
VOID (Linux) 64bit

chain_reaction

  • New Member
  • *
  • Posts: 22
Re: how to check to see if TStringList has been created?
« Reply #1 on: February 13, 2014, 07:03:20 am »
FindAllFiles() is always create instance of TStringList as the result. NIL means memory address not valid or not allocated and accessing the nil will raise a violation access warning.

I think you should carefully using the FindAllFiles() routine.

mangakissa

  • Hero Member
  • *****
  • Posts: 1131
Re: how to check to see if TStringList has been created?
« Reply #2 on: February 13, 2014, 09:09:47 am »
TStringlist is never create itself. It's an object and must ALWAYS created into memory.
Code: [Select]
procedure foo;
var sl : TStringlist;
begin
  sl := TStringlist.create;
  try
    try
      sl.add('RTFM');
    except
        showmessage('error');
    end;
  finally
    sl.free;
  end;
end;

In this case, the function give s Tstringlist back. But this is also an object and must be freed (http://wiki.freepascal.org/findallfiles)

I remember to tell this exactly on a dutch forum
« Last Edit: February 13, 2014, 09:31:39 am by mangakissa »
Lazarus 2.06 (64b) / FPC 3.0.4 / Windows 10
stucked on Delphi 10.3.1

Michl

  • Full Member
  • ***
  • Posts: 226
Re: how to check to see if TStringList has been created?
« Reply #3 on: February 13, 2014, 09:28:52 am »
TStringlist is never create itself - thats correct. In this case the StringList is created by FindAllFiles.

Have a look at the code:
Code: [Select]
function FindAllFiles(const SearchPath: String; SearchMask: String;
  SearchSubDirs: Boolean): TStringList;
var
  Searcher: TListFileSearcher;
begin
  Result := TStringList.Create;
...
So you need not create "Form1.ImageList" before, it produces only a memoryleak.
Code: [Select]
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;

serbod

  • Full Member
  • ***
  • Posts: 146
Re: how to check to see if TStringList has been created?
« Reply #4 on: February 13, 2014, 09:31:50 am »
Use Assigned() to check.

mangakissa

  • Hero Member
  • *****
  • Posts: 1131
Re: how to check to see if TStringList has been created?
« Reply #5 on: February 13, 2014, 09:33:30 am »
I was puting more information to the topic back, but you were faster than me  :D
Lazarus 2.06 (64b) / FPC 3.0.4 / Windows 10
stucked on Delphi 10.3.1

Michl

  • Full Member
  • ***
  • Posts: 226
Re: how to check to see if TStringList has been created?
« Reply #6 on: February 13, 2014, 09:57:16 am »
@ userx-bw:
In such a case I would create "Form1.ImageList" by Form1.OnCreate (now you have a empty StringList, but always useable/assigned) and free it by Form1.OnDestroy. So you never have to test, its created.

In your procedure, where you fill "Form1.ImageList", use simply a new StringList, what you can free, after assigning it to your ImageList.

e.G.:
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var
  SL: TStringList;
begin
  SL:=FindAllFiles('', '*.*', True);
  ImageList.Assign(SL);
  SL.Free;
end;
« Last Edit: February 13, 2014, 06:13:27 pm by Michl »
Code: [Select]
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;

userx-bw

  • Full Member
  • ***
  • Posts: 178
Re: how to check to see if TStringList has been created?
« Reply #7 on: February 13, 2014, 04:21:11 pm »
FindAllFiles() is always create instance of TStringList as the result. NIL means memory address not valid or not allocated and accessing the nil will raise a violation access warning.

I think you should carefully using the FindAllFiles() routine.
TStringlist is never create itself. It's an object and must ALWAYS created into memory.
Code: [Select]
procedure foo;
var sl : TStringlist;
begin
  sl := TStringlist.create;
  try
    try
      sl.add('RTFM');
    except
        showmessage('error');
    end;
  finally
    sl.free;
  end;
end;

In this case, the function give s Tstringlist back. But this is also an object and must be freed (http://wiki.freepascal.org/findallfiles)

I remember to tell this exactly on a dutch forum
TStringlist is never create itself - thats correct. In this case the StringList is created by FindAllFiles.

Have a look at the code:
Code: [Select]
function FindAllFiles(const SearchPath: String; SearchMask: String;
  SearchSubDirs: Boolean): TStringList;
var
  Searcher: TListFileSearcher;
begin
  Result := TStringList.Create;
...
So you need not create "Form1.ImageList" before, it produces only a memoryleak.
@ userx-bw:
In such a case I would create "Form1.ImageList" by Form1.OnCreate (now you have a empty StringList, but always useable/assigned) and free it by Form1.OnClose. So you never have to test, its created.

In your procedure, where you fill "Form1.ImageList", use simply a new StringList, what you can free, after assigning it to your ImageList.

e.G.:
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var
  SL: TStringList;
begin
  SL:=FindAllFiles('', '*.*', True);
  ImageList.Assign(SL);
  SL.Free;
end;

Now that this has turned into a two topic discussion:

Sorry for the poor sentence structure, when I wrote,
Quote
the TStringList creates itself
  What was meant by what I said is that I myself do not create the Object, but the people that wrote FREE PASCAL, by there code it is created, therefore following the rule, the programmer that creates the object has the responsibility to free it.

Therefore who ever wrote FREE PASCAL, and wrote that function FindAllFiles to create the TStringList now have the responsibility to free that Object that they called to be created by what ever means necessary.

If they, the programmers that wrote the function FindAllFiles, if they themselves have not done this then they have violated there own rules, and the Programming Language is therefore not written correctly, in freeing that Object that was created by there own code that they wrote not I, or another user of this programming language.

It should then have been written to do as follows.


When you call the function FindAllFiles it has to check to see if an hinstance of  the Object TStringList has been created first if NOT then throw error the variable name for TStringList Not Created.

Just like I am trying to find out how to do.


Because what I am checking for is:

If the user of this program sets the working directory or NOT before he clicks the button to execute the program, if he does not set the directory that he wants to use first before he clicks the other button to execute this program that then executes the external program then show a message to tell him that he forgot to set a directory to work out of.

It is because FREE PACAL uses the Function FindAllFIiles to create the TStringList then fills it, the responsibility to free the List is no longer mine, but the people that wrote FREE PASCAL therefore leaving me with just having to check to be sure it got filled, not created.

To know if the user set a directory or not. One would be to see if the Object was created, two see if it has anything in it would this not be the way to do this?

By my code when the user sets the directory it calls FindAllFIles the Object is created then filled by that function.

Therefore all I was doing is trying one of the ways to check to see if the user set the working directory first, because if the user clicks the button I use this program to execute the external program before setting the working directory it is now trying to use an Object that has not yet been created or filled because the function FindAllFiles was never called to create the Object then fill it.

In any stage of the code that is used to create an Object there needs to be code to be sure that is has been created just in case it does not get created for what ever reason. How else does the compiler or Lazarus IDE know if an Object has been created or not to give you or me an error when you are in the developing stages using there IDE when working with an Object?


going back to my reason for writing this question, What is the best way to check to see if a TStringList has even been created so I can check to see if the user even set a working directory so I can stop this program from calling the external program to execute?

Even if I create an Object myself then how do I check to be sure that it in fact it has been created before I try to use it?
My Finished Projects
https://sourceforge.net/projects/mhsetroot/
https://sourceforge.net/projects/gmhsetrootfreepascalfrontend/

HP Elitetbook 6930p Dual Core Intel vPro 2.66 gHz
VOID (Linux) 64bit

Michl

  • Full Member
  • ***
  • Posts: 226
Re: how to check to see if TStringList has been created?
« Reply #8 on: February 13, 2014, 04:29:21 pm »
What is the best way to check to see if a TStringList has even been created

Use Assigned() to check.
Code: [Select]
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;

Leledumbo

  • Hero Member
  • *****
  • Posts: 8835
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: how to check to see if TStringList has been created?
« Reply #9 on: February 13, 2014, 04:54:27 pm »
Quote
What was meant by what I said is that I myself do not create the Object, but the people that wrote FREE PASCAL, by there code it is created, therefore following the rule, the programmer that creates the object has the responsibility to free it.

Therefore who ever wrote FREE PASCAL, and wrote that function FindAllFiles to create the TStringList now have the responsibility to free that Object that they called to be created by what ever means necessary.

If they, the programmers that wrote the function FindAllFiles, if they themselves have not done this then they have violated there own rules, and the Programming Language is therefore not written correctly, in freeing that Object that was created by there own code that they wrote not I, or another user of this programming language.
There's no such an enforced rule, it's perfectly fine to return a object that must be freed. Some APIs already mention that in the documentation, but FindAllFiles seems not yet properly documented. This should be filed as a documentation enhancement instead. The way I use such an API is usually like this:
Code: [Select]
with FindAllFiles(...) do
  try
    .. // do something with the result
  finally
    Free;
  end;
Think about how the code should Free the created TStringList object. It's possible though to change the signature to:
Code: [Select]
procedure FindAllFiles(Result: TStringList; <other parameters>);and let the code check whether Result is properly initialized or not and raise exception if so. However, such a signature is IMHO more dangerous. If Result is a local variable and it's not initialized by the programmer (with nil), then FindAllFiles will keep processing despite Result points to invalid address, which could end up in unexpected behavior.

userx-bw

  • Full Member
  • ***
  • Posts: 178
Re: how to check to see if TStringList has been created?
« Reply #10 on: February 13, 2014, 04:58:33 pm »
What is the best way to check to see if a TStringList has even been created

Use Assigned() to check.

I was just getting to that one, but does it then have to be used like this?

Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var
  SL: TStringList;
begin
  SL:=FindAllFiles('', '*.*', True);
  ImageList.Assign(SL);
  SL.Free;
end;

why would I want to create two List when I only need one?


why could I not use
Code: [Select]
Form1.ImageList := FindAllFiles(ExtractFilePath(Form1.ImageFile), '*.*', false);
  Form1.ImageList.Sort;
....

Because AGAIN, the function creates the Object if that function fails then how does the programmer know if it failed or not?


what is the way to check if the Object was created in the first place?
My Finished Projects
https://sourceforge.net/projects/mhsetroot/
https://sourceforge.net/projects/gmhsetrootfreepascalfrontend/

HP Elitetbook 6930p Dual Core Intel vPro 2.66 gHz
VOID (Linux) 64bit

userx-bw

  • Full Member
  • ***
  • Posts: 178
Re: how to check to see if TStringList has been created?
« Reply #11 on: February 13, 2014, 05:47:40 pm »
Code: [Select]
with FindAllFiles(...) do
  try
    .. // do something with the result
  finally
    Free;
  end;

correct me if I am wrong but does not freeing the object getting rid of the object, therefore I can no longer use the object as it was freed?

Because if I do it that way it just messes up all of my other code because I need to use this list the entire time the program is running that would mean I'd have to rewrite and get rid of a LOT of other functions and procedures I have already written to make this work, I am now in the final stages of finishing this program and just doing the error checking that I need to do now to finish it up.

off the top of my head let me see what I'd do ...
Code: [Select]

with FindAllFiles(ExtractFilePath(Form1.ImageFile), '*.*', false) do
  try
    .. // do something with the result
 Form1.ImageList := FindAllFiles(ExtractFilePath(Form1.ImageFile), '*.*', false);
 Form1.ImageList.Sort;
 
TForm1.Button2Click ( self) ;

//  within that Procedure does
all of my error checking then if everything
is good then it calls ...

timer.enabled := true;

// then sets that to call

RunExternalProgram.SetCycleBackGround;
 
//which inside that procedure calls

Functions.setColors;   

Functions.SetArgsForOneColor;

Functions.SetArgsForTwoColors; 

Functions.CandyStripes;

Functions.CandyStripesAlpha;   

//That all depending on what is set for it to
call which ever one, then sets the rest of the
Args then calls to execute the external program
that has to keep re calling it at a set time which
inside this procedure too calls to
free the TProcess then ...
 
 finally
    TStringList.Free;
  end;


If I free the list too soon then I will have to keep re recreating it and filling it then sorting it and that throws everything out of sync.

This is the same program that we talked about with me trying to figure out how to use Threads, I am now using the TTimer instead. and now it is almost done all I really have to do is this error checking and add like two more things for it to do, give it a good once over to be sure of everything  then it is finished.

Let me think this over a bit to see what I can come up with now ..

but the question remains

when you free an object it is no longer able to be used as it gets rid of it.



 
 
« Last Edit: February 13, 2014, 06:04:30 pm by userx-bw »
My Finished Projects
https://sourceforge.net/projects/mhsetroot/
https://sourceforge.net/projects/gmhsetrootfreepascalfrontend/

HP Elitetbook 6930p Dual Core Intel vPro 2.66 gHz
VOID (Linux) 64bit

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: how to check to see if TStringList has been created?
« Reply #12 on: February 13, 2014, 06:06:36 pm »
Code: [Select]
with FindAllFiles(...) do
  try
    .. // do something with the result
  finally
    Free;
  end;

correct me if I am wrong but does not freeing the object getting rid of the object, therefore I can no longer use the object as it was freed?

But you've already used the object in the "// do something with the result" block.

If you really want a stringlist that persists throughout your program's lifetime you can create it in the main form's OnCreate (or an initialization section), assign data to it from a FindAllFiles() object that you then free, and free your stringlist in the main form's OnDestroy (or in a finalization section).
However, a list of files quickly goes stale, since you have no control over what files the user might create, delete or move. So you're far better to use leldumbo's suggestion, and ensure your file list is up-to-date, yet does not leak memory.

userx-bw

  • Full Member
  • ***
  • Posts: 178
Re: how to check to see if TStringList has been created?
« Reply #13 on: February 13, 2014, 06:45:42 pm »
Code: [Select]
with FindAllFiles(...) do
  try
    .. // do something with the result
  finally
    Free;
  end;

correct me if I am wrong but does not freeing the object getting rid of the object, therefore I can no longer use the object as it was freed?

But you've already used the object in the "// do something with the result" block.

If you really want a stringlist that persists throughout your program's lifetime you can create it in the main form's OnCreate (or an initialization section), assign data to it from a FindAllFiles() object that you then free, and free your stringlist in the main form's OnDestroy (or in a finalization section).
However, a list of files quickly goes stale, since you have no control over what files the user might create, delete or move. So you're far better to use leldumbo's suggestion, and ensure your file list is up-to-date, yet does not leak memory.

that do something code block was leldumbo's I just stuck stuff inside of it showing him what I might do with that bit of code ...

the directory I am using is just stored images what the user wants to use to put up on his or her screen for wallpaper .. if they remove an image while the program is running then yes it would look for an image that is not there any longer, then I'd just write in my code somewhere to double check to see if that reference to that file is still there before sending it to be used if not there then remove that from the list and pick a different list item. ( which I just came to me, so I'll do that part) thanks for the  what if question about the user changes the files in the directory thing.

I am just simply trying to see if the user set a directory that has the images in it so that i is filled with the files error if he forgot to do that then message to him telling him to do that first before trying to run the program.

The freeing this List Object I put that in the Form OnDistroy  leaving the FindAllFiles to create it as that functions calls for it to be created, then fills it.

My Finished Projects
https://sourceforge.net/projects/mhsetroot/
https://sourceforge.net/projects/gmhsetrootfreepascalfrontend/

HP Elitetbook 6930p Dual Core Intel vPro 2.66 gHz
VOID (Linux) 64bit

mangakissa

  • Hero Member
  • *****
  • Posts: 1131
Re: {SOVED} how to check to see if TStringList has been created?
« Reply #14 on: February 14, 2014, 09:30:18 am »
Do you really understand how OOP works?

function FindAllFiles() creates an object of TStringlist and give it back to your declared variable. If the function releases the object, there's nothing to give back then a NIL.  FindAllFiles() does nothing more back than the pointer of the created object in the function.
Offcource you can check on Assign(), but this function does not always give the right result.
In my opinion this function is the best way:
Code: [Select]
procedure foo;
var FileList : TStringList;
begin
  try
     try
        FileList := FindAllFiles();
        showmessage(FileList.text);
     except
         //-- there's some wrong with the result of FindAllFiles.
         //-- maybe the result is NIL and therefore this except will be called
         showmessage('No list detected');
     end;
  finally
     // always release your object from memory. Even if it not exist
     // because finally always called after the normal procedure loop or error.
     FileList.free; //(FileList.freeandnil)  -- remove object from memory
  end;
end;

Conclusion: always release created objects.
Lazarus 2.06 (64b) / FPC 3.0.4 / Windows 10
stucked on Delphi 10.3.1

 

TinyPortal © 2005-2018