Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2004-02

TObjectList.free

12 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Charl van Jaarsveldt

Hi all,

According to the docs for TObjectList, if it's OwnsObjects property is set to true, then, if you clear the list, it will automatically call free for all the objects contained in the list. At least that is how I understand it.
Now, I did a little test program and found that calling TObjectList.clear actually does not call free for each object in the list. If I run through the list and call free for each list manually it works fine though.

So, here is the question: Is this normal behaviour? If so, when precisely is the list elements going to be freed then? Must it always be freed manually?

I guess this is a problem I have with a couple of things in the FCL/VCL, so an answer to this will be greatly appreciated! :-)

Regards,
Charl

Unknown author
to Charl van Jaarsveldt
Charl van Jaarsveldt wrote 10 lines
Hi all, According to the docs for TObjectList, if it's OwnsObjects property is set to true, then, if you clear the list, it will automatically call free for all the objects contained in the list. At least that is how I understand it. Now, I did a little test program and found that calling TObjectList.clear actually does not call free for each object in the list. If I run through the list and call free for each list manually it works fine though.

I fixed this. The problem was that the behaviour of Borland's TList changed
- it got (a lot!) slower. In older TList implementations TList.Clear didn't do anything except free the memory for the list elements. Now it calls Notification for all elements in the list, which is a time consuming task.

Show quoted text 7 lines
So, here is the question: Is this normal behaviour? If so, when precisely is the list elements going to be freed then? Must it always be freed manually? I guess this is a problem I have with a couple of things in the FCL/VCL, so an answer to this will be greatly appreciated! :-)

I have a fix in place, but can't currently test as someone else's work in the RTL currently stops me from compiling the Classes/Contnrs units.

As soon as the fix is committed, I'll notify the mailing list.

Michael.

Matt Emson
to Unknown author
I fixed this. The problem was that the behaviour of Borland's TList

changed

- it got (a lot!) slower. In older TList implementations TList.Clear

didn't

do anything except free the memory for the list elements. Now it calls Notification for all elements in the list, which is a time consuming task.

Yes, but this is actually cool though because you can get event based notifications when any element is removed. That's why they did it.

Matt

Unknown author
to Matt Emson
Matt Emson wrote 10 lines
> I fixed this. The problem was that the behaviour of Borland's TList changed > - it got (a lot!) slower. In older TList implementations TList.Clear didn't > do anything except free the memory for the list elements. > Now it calls Notification for all elements in the list, which is a time > consuming task. Yes, but this is actually cool though because you can get event based notifications when any element is removed. That's why they did it.

I understand their reasons, but it's not so cool if you don't care about this event and have a list of 10000 elements. It's a serious performance penalty in such case. It would have been better if this behaviour had been optional (remember, it appeared only in later Delphi versions). As soon as I figure out how, I will change the FPC implementation so this doesn't happen unless really needed.

Michael.

Unknown author
to Charl van Jaarsveldt: According to the docs for TObjectList, if it's OwnsObjects property is set to true, then,…
Charl van Jaarsveldt wrote 17 lines
Hi all, According to the docs for TObjectList, if it's OwnsObjects property is set to true, then, if you clear the list, it will automatically call free for all the objects contained in the list. At least that is how I understand it. Now, I did a little test program and found that calling TObjectList.clear actually does not call free for each object in the list. If I run through the list and call free for each list manually it works fine though. So, here is the question: Is this normal behaviour? If so, when precisely is the list elements going to be freed then? Must it always be freed manually? I guess this is a problem I have with a couple of things in the FCL/VCL, so an answer to this will be greatly appreciated! :-)

I have committed a fix in the 1.9.X RTL.

Michael.

Dean Zobec
to Unknown author: I understand their reasons, but it's not so cool if you don't care about this event and…

Alle 12:25, domenica 15 febbraio 2004, ha scritto:

Show quoted text 12 lines
> > I fixed this. The problem was that the behaviour of Borland's TList > changed > > - it got (a lot!) slower. In older TList implementations TList.Clear > didn't I understand their reasons, but it's not so cool if you don't care about this event and have a list of 10000 elements. It's a serious performance penalty in such case. It would have been better if this behaviour had been optional (remember, it appeared only in later Delphi versions). As soon as I figure out how, I will change the FPC implementation so this doesn't happen unless really needed.

I really appreciate that you noticed the problem. To avoid the problem and gain in speed in Delphi I was using a clone of TList without the notification mechanism.
Indeed the way TObjectList was introduced with Delphi 5 was not a clever move IMHO.
In that occasion the TList was changed to accomodate the need of the one and only descendant TObjectList, which is against any object-oriented design rule.
And worse, as I see it, TObjectList should not be a descendant of TList at all. TList was not designed to be an ancestor class like TStrings for example. They would be better off creating TObjectList (derived from TObject and not TList) as a wrapper class around the TList. I'm happy I can count on you for things like that. The more I work with fpc, the more I like it. Thank you for the great work you are doing.
Ciao, Dean

Matthews
to Unknown author: I fixed this. The problem was that the behaviour of Borland's TList changed - it got (a…

Hello all.

I'm using a function and a procedure, both which deal with finding files in the same directory, and then either counting them, or reading them, but I'm getting some very weird values for DosError. I'm using v1.0.10, and I continue to get a value of 183 from DosError in the function (which is in my unit), but a DosError value of 0 from the procedure inside the main file. The code is below.

Does anybody know what DosError 183 means, and if so, can I avoid this in any way?

Thanks.

-Lukas M.

PS Does anybody have a more elegant solution to determine when there are no more files in a directory? I had to use the workaround of duplicate filenames because DosError was always 0.

This is the setup:

var
     dir_in:string;
     dir_out:string;
Procedure Main;
	begin
// Normally set from the command line, but dir_in and dir_out are always
these values.
	        dir_in := 'C:\2dapad\in'; // This directory has 64 files in it
(all 2DAs)
	        dir_out := 'C:\2dapad\pad';
                   num_files := NumberOfFiles(dir_in,'*.2da');
	        if num_files = 0 then EndProgram('There were no files.') // Just
halts the program and writes a message on screen.
                   else if num_files = -1 then EndProgram('Unable to open '
+ dir_in)
                   else if num_files = -2 then EndProgram('DosError in ' +
dir_in);
                   // Num_files always equals 1.
	        GetBatchFile;
	end;
Function NumberOfFiles(path,ext:string):longint;
// Searches through the passed directory (if one is given) for files of a
particular extension.
// '' for ext = '*.*'
// Note: This is the function that does't work (the one in my unit)
      var
         i:longint;
         q:longint;
         curr,old:string;
         temp:TSearchRec;
         ex:string;
      begin
           i := 0;
           curr := GetCurrentDir;
           if (ext = '') OR (ReplaceChrStr(ext,'.','') = ext) then ex := '*.*'
           else ex := ext;
           if path  '' then
              begin
                   GetShortName(path);
                   if SetCurrentDir(path) = FALSE then NumberOfFiles := -1;
// If there's an error, exit soon.
              end;
           FindFirst(ex,anyfile,temp);
           q := DosError;
// Right here, this function ends, because DosError = 183.
           if q  0 then
              begin
                   writeln('DosError = ' + IntToStr(q));
                   repeat until readkey  '';
                   NumberOfFiles := -2;
              end;
           inc(i);
           old := temp.name;
           FindNext(temp);
           q := DosError;
           if (q = 0) AND (temp.name  old) then
              begin
                   inc(i);
                   old := '';
                   while ((old = '') OR (DosError = 0)) AND (temp.name
old) do
                         begin
                              old := temp.Name;
                              FindNext(temp);
                              inc(i);
                         end;
              end;
           FindClose(temp);
           GetShortName(curr);
           if (path  '') then SetCurrentDir(curr);
           NumberOfFiles := i;
      end;
// This the function in the main file, that does work.
// pads_skipped and pads_created are just global counters for number of
files already dealth with.
// dir_out is also set by the user.
Procedure GetBatchFile;
      var
         f:tSearchRec;
         curr:string;
         i:integer;
         label batch_search;
      begin
           batch_search: // I know I'm bad...
           if name_in  '' then last_file := ExtractFileName(name_in) else
last_file := '';
           curr := GetCurrentDir;
           GetShortName(dir_in);
           if SetCurrentDir(dir_in) = FALSE then EndProgram('Error: Unable
to change directory from ' + GetCurrentDir + ' to ' + dir_in);
           i := 0;
           FindFirst('*.2da',anyfile,f);
           i := DosError;
// Right here, and later, DosError is always 0.
           if i  0 then
              begin
                   Log('DosError = ' + IntToStr(i));
                   name_in := '??_BATCH_END';
                   FindClose(f);
                   GetShortName(curr);
                   SetCurrentDir(curr);
                   exit;
              end;
           i := 0;
           while (i < (pads_created + pads_skipped)) AND (DosError = 0) do
// Keep going until a new file is found (the nth file in the list.)
                 begin
                      FindNext(f);
                      inc(i);
                 end;
           if (DosError  0) OR (last_file = f.Name) then
              begin
                   name_in := '??_BATCH_END';
                   FindClose(f);
                   GetShortName(curr);
                   SetCurrentDir(curr);
                   exit;
              end
           else
               begin
                    GetShortName(curr);
                    SetCurrentDir(curr);
                    name_in := dir_in + f.Name;
                    FindClose(f);
                    if dir_in[length(dir_in)]  '\' then
insert('\',name_in,length(dir_in)+1);
                    name_out := dir_out +
ChangeFileExt(ExtractFileName(name_in),'.pad');
                    if dir_out[length(dir_out)]  '\' then
insert('\',name_out,length(dir_out)+1);
                    if (FileExists(name_out)) AND (overwrite = FALSE) then
                       begin
                            inc(pads_skipped);
                            Log('PAD for ' + ExtractFileName(name_in) + '
already exists - skipped.');
                            goto batch_search;
                       end;
               end;
      end;
Unknown author
to Matthews

From: "Matthews"
To:
Sujbect: [fpc-pascal] Weird DosError values
Date sent: Mon, 16 Feb 2004 18:06:13 -0500

Hello Lukas

Show quoted text 7 lines
I'm using a function and a procedure, both which deal with finding files in the same directory, and then either counting them, or reading them, but I'm getting some very weird values for DosError. I'm using v1.0.10, and I continue to get a value of 183 from DosError in the

.
.

We'd probably need little bit more information from you. First of all, your code snippet isn't directly compilable as it is now - it isn't even completely clear which FindFirst function is being used (my guess is that one from SysUtils because of the TSearchRec type used, but on the other hand you're using DosError as well, which is relevant to FindFirst from unit Dos). Second, it would be definitely useful to know the target you're compiling for (GO32v2?, ???) and the operating system you're running on.

Regarding your code - well, I'd definitely suggest to use something like while..do or repeat..until instead of your use of goto construct.

Best regards

Tomas

VOLNY klub: Modemisti vseho druhu, spojte se! http://klub.volny.cz
Matthews
to Unknown author

Dear Tomas,

Thanks for your advice.

My apologies for not providing enough information - I realized after I sent the message that I should have mentioned what OS, etc. I was running.

I'm running Win 2000, and using sysutils, and dos - could that be the problem?

The target os (as given to my by DevPascal 1.9.2) is Win32 for i386.

However, I downloaded the 1.9.2 w32 version of FreePascal, and the program compiled fine, and hasn't given me any errors since (no odd DosError values). Thanks for your suggestion on resolving the use of goto. I'll implement that soon.

One question: In the future, should I just host my code on geocities (or something) and then include a link to it instead?

-Lukas

you wrote 44 lines
From: "Matthews" To: Sujbect: [fpc-pascal] Weird DosError values Date sent: Mon, 16 Feb 2004 18:06:13 -0500 Hello Lukas > I'm using a function and a procedure, both which deal > with finding files in > the same directory, and then either counting them, or > reading them, but I'm > getting some very weird values for DosError. I'm using > v1.0.10, and I > continue to get a value of 183 from DosError in the . . We'd probably need little bit more information from you. First of all, your code snippet isn't directly compilable as it is now - it isn't even completely clear which FindFirst function is being used (my guess is that one from SysUtils because of the TSearchRec type used, but on the other hand you're using DosError as well, which is relevant to FindFirst from unit Dos). Second, it would be definitely useful to know the target you're compiling for (GO32v2?, ???) and the operating system you're running on. Regarding your code - well, I'd definitely suggest to use something like while..do or repeat..until instead of your use of goto construct. Best regards Tomas -- VOLNY klub: Modemisti vseho druhu, spojte se! http://klub.volny.cz _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Marco van de Voort
to Matthews
Show quoted text 16 lines
Thanks for your advice. My apologies for not providing enough information - I realized after I sent the message that I should have mentioned what OS, etc. I was running. I'm running Win 2000, and using sysutils, and dos - could that be the problem? The target os (as given to my by DevPascal 1.9.2) is Win32 for i386. However, I downloaded the 1.9.2 w32 version of FreePascal, and the program compiled fine, and hasn't given me any errors since (no odd DosError values). Thanks for your suggestion on resolving the use of goto. I'll implement that soon. One question: In the future, should I just host my code on geocities (or something) and then include a link to it instead?

How large is your buffer? Do you try to read 2/4/8k blocks ?

Unknown author
to Matthews: Thanks for your advice. My apologies for not providing enough information - I realized…

From: "Matthews"
To:
Subject: Re: [fpc-pascal] Weird DosError values Date sent: Wed, 18 Feb 2004 16:13:23 -0500

Hi Lukas

I'm running Win 2000, and using sysutils, and dos - could that be the problem?

Yes, that is the problem. You have to make sure that either you're using that FindFirst from unit Dos (e.g. by calling it using "Dos.FindFirst", "Dos.FindNext" and "Dos.FindClose"), or change the way of checking for errors (SysUtils doesn't use DosError).

Show quoted text 5 lines
However, I downloaded the 1.9.2 w32 version of FreePascal, and the program compiled fine, and hasn't given me any errors since (no odd DosError values).

I would guess that the reason why it works now is that you might have changed the order of units in your "uses" clause. You shouldn't rely on this, and make the selection explicit.

One question: In the future, should I just host my code on geocities (or something) and then include a link to it instead?

It depends. The best solution is to shrink problematic code to the shortest needed amount (i.e. something which still compiles and shows the problem at the same time). In this case you can still place it inline in your message. If you cannot do that and the code is larger than something like 20-30 lines but below something like 2-3 kB, you can add it as an attachment to your message. If it's larger then placing it somewhere at WWW or FTP and just sending the link is probably the best solution.

Tomas

VOLNY klub: Modemisti vseho druhu, spojte se! http://klub.volny.cz