Solved

Free ListBox-Objects before closing the application

Posted on 2001-09-14
13
198 Views
Last Modified: 2010-04-06
0
Comment
Question by:NicoleKabitzki
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 3
  • +2
13 Comments
 
LVL 22

Expert Comment

by:Mohammed Nasman
ID: 6482106
what do u want exactly?
0
 
LVL 8

Accepted Solution

by:
TOndrej earned 200 total points
ID: 6482164
you can do it in the form's OnDestroy:

procedure TForm1.ClearListBoxItems;
var
  I: Integer;
  MyObject: TObject;
begin
  with ListBox1.Items do
    for I := 0 to Count - 1 do
      Objects[I].Free;
end;

procedure TForm1.FormDestroy; // OnDestroy event handler
begin
  ClearListBoxItems;
end;
0
 
LVL 1

Expert Comment

by:malsoft
ID: 6482274
Just to expand a little on TOndrei's comment, I would add some exception handling into the clearing code, just in case something goes awry:

procedure TForm1.ClearListBoxItems;
var
  I: Integer;
begin
  with ListBox1.Items do
    for I := 0 to Pred(Count) do
      try
        Objects[I].Free;
      except
      end;
end;
0
[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

 

Author Comment

by:NicoleKabitzki
ID: 6482354
0
 

Author Comment

by:NicoleKabitzki
ID: 6482355
0
 

Expert Comment

by:duti
ID: 6485553
A constructive comment on response above.

Normally it's not a good idea to eat exceptions.  Exceptions indicate problems, and they are very usefull when debugging. Certainly when your application is running at a customer's office, and you don't have Delphi there.

procedure TForm1.ClearListBoxItems;
var
 I: Integer;
begin
 with ListBox1.Items do
   for I := 0 to Count - 1 do
     if assigned(Objects[I]) then Objects[I].Free;
end;
0
 
LVL 8

Expert Comment

by:TOndrej
ID: 6485675
Hi duti,

TObject.Free checks for nil, therefore your check

if Assigned(Objects[I]) then ...

is not necessary.
0
 
LVL 1

Expert Comment

by:malsoft
ID: 6485752
duti,

Admittedly, "eating exceptions" is a BAD THING generally, but there are valid reasons for doing so in this instance. Plus, if you wanted to, you could add proper catching of the error(s) you might expect and re-raise the unhandled ones as needs be...

However, in this occasion we _do_ need to eat the exceptions. The loop in which the freeing is done will continue to work even if one object has already been Free'd, but the pointer referencing it is non-nil (which is normal for a Free operation). In those instances, Free'ing an already Free'd object will result in an EAccessViolation error and display an "error dialog". The same would also happen for the Assigned(Objects[I]) operation as well. If the object is Free'd, but the pointer is not nil'd afterwards, the condition will be fulfilled and you'll get an EAccessViolation error again.
0
 
LVL 8

Expert Comment

by:TOndrej
ID: 6485788
Hi malsoft,

I haven't looked at your code until now ;-)

> The loop in which the freeing is done
will continue to work

Which is IMHO wrong. The exception should not be suppressed.

> The loop in which the freeing is done
will continue to work even if one object has already been Free'd, but the pointer referencing it is
non-nil (which is normal for a Free operation).

If there is code that Frees objects referenced by the listbox items (which would be poor design, IMHO) then additional work is required to provide notification to the listbox to remove the item and reference.
Keeping invalid references doesn't make sense and is dangerous. So is your exception suppressing mechanism.

Just my 2c.
TOndrej
0
 
LVL 1

Expert Comment

by:malsoft
ID: 6485897
Hi TOndrej,

I said
> The loop in which the freeing is done
will continue to work

You said
>Which is IMHO wrong. The exception should not be suppressed.

However, you missed my point that you _can_ add whatever exception handling you want in there if you wanted to:

eg
  try
    // ...
  except
    on EAccessViolation do begin
      // handle already Free'd instances here
      end;
    on EException do
      // Everything else gets raised again
      raise;
  end;

As this code will be (normally) called within the context of the OnDestroy event, we need to ensure that the destruction completes, otherwise we end up with a memory leak (the remainder of the list will be skipped, leaving objects floating around in memory limbo).

You then said:
> If there is code that Frees objects referenced by the listbox items (which would be poor design, IMHO) then additional work is required to provide notification to the listbox to remove the item and reference.

This I would agree with, but as we do not know the nature of the objects that will be added to the list, some assumptions must be made. Here's an example for you: Say the objects added to the list were actual controls, created dynamically. To get them to display correctly, you need to assign them a Parent. When this Parent is notified of the Form's destruction, any child-control will also be destroyed at the same time (you don't call the Free method, the Parent tells all children to destroy themselves). When you come to do your own clean-up, you may try to Free the control you dynamically created and you will then get an EAccessViolation error because the object is already destroyed, but the reference to it is non-nil, hence Assigned() would still work and Free would attempt to re-Free the memory as it is not a nil value.

You said:
> Keeping invalid references doesn't make sense and is dangerous. So is your exception suppressing mechanism.

Keeping invalid references, I would whole-heartedly agree with. However, taking the above example into account, there's not much you can do about it. You either let the loop complete, freeing ALL objects, or you risk leaving some of the objects "floating around" inside the applications memory space when the unhandled exception jumps you out of the loop. In those occasions, the exception suppression is an asset rather than a liability.

I've not got any pennies to hand, but I've got a nickel! (that's inflation for you), so the tally stands at: 200pts and 7cents ;-)
0
 

Expert Comment

by:duti
ID: 6486020
Hi malsoft,

you got a point there, that the loop should continue. Even when one object could not be freed, the rest should at least be tried.  But using the 'assigned'-test, you can skip the exception-stuff and so make the code a little bit more readable. (if you are certain that uninitialized pointers will be nil)
And doing so, we use lesser keystrokes ;-)



Hi TOndrej,

TObject.Free might check if it is nil, the code never get that far, because 'Free' is a method of an object, and if the object itself is nil, the code will do an EAccessViolation before calling 'Free'.  I believe the procedure SysUtils.FreeAndNil would be more appropriate. (so it's shorter, readable, and saves even more keystrokes.)

But unfortunately the code
  FreeAndNil(ListBox1.items.Objects[1]);
won't compile. :(  
("Constant object cannot be passed as var parameter")

0
 
LVL 8

Expert Comment

by:TOndrej
ID: 6486716
duti,

> TObject.Free might check if it is nil, the code never
> get that far, because .... <snip>

try it:

var
  Obj: TObject;
begin
  Obj := nil;
  Obj.Free;
end;

> when one object could not be freed, the rest
should at least be tried
I disagree as I explained above.

malsoft,
> Parent tells all children to destroy themselves

and you need to get a notification of this so you can update your references...

> When you come to do your own clean-up, you may try
> to Free the control you dynamically created and you
> will then get an EAccessViolation error because the
> object is already destroyed

...exactly, to make sure this thing never happens.

> you risk leaving some of the objects "floating around" inside the applications memory space

Agreed. It seems to be a matter of taste. I prefer seeing all error messages. If there is an error in freeing an object, I want to know about it. I try to take enough precautions to never release code that would raise errors in object destruction; however if I do, I want the user to see it and hopefully report it, so I can fix it.

Cheers for an interesting discussion, and
Have a nice Delphi day :-)
TOndrej
0
 

Author Comment

by:NicoleKabitzki
ID: 6486744
Ok, that works! Thanx for your answer.

Bye
  Nicole
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
NetCrunch network monitor is a highly extensive platform for network monitoring and alert generation. In this video you'll see a live demo of NetCrunch with most notable features explained in a walk-through manner. You'll also get to know the philos…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Suggested Courses
Course of the Month8 days, 13 hours left to enroll

615 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question