Board index » delphi » Events occurring after the FormDestroy event

Events occurring after the FormDestroy event

I just ran into something strange in one of my D3 programs.  Events, in
my main form, are occurring after the FormDestroy event.  I don't think
this is normal behavior, but I could be mistaken.  My FormResize event
and ListViewChange event both are firing after the FormDestroy event.  I
then receive an Access Violation because object that were freed in the
FormDestroy are referenced in the ListViewChange event.  Is this a bug
or am I just going crazy?

Here is the sequence:  FormDestory -> FormResize -> ListViewChange ->
Access Violation

Here is the partial source:

//------------------------------------------------------------------------------

procedure TFormMain.FormResize(Sender: TObject);
var
  I: Integer;
begin
  { Set defaults }
  I := Abs(Round(100 - (Screen.Height / Height * 100)));
  {}
  if (I >= 30) then // 30%
    CaptionBar.ShowStyle := ssSmall
  else
    CaptionBar.ShowStyle := ssLarge;
end;
//------------------------------------------------------------------------------

procedure TFormMain.FormDestroy(Sender: TObject);
begin
  Application.HelpCommand(HELP_QUIT, 0);
  { Free References }
  Rep.Free;
  PictureSmall.Free;
  PictureLarge.Free;
end;
//------------------------------------------------------------------------------

procedure TFormMain.ListViewChange(Sender: TObject; Item: TListItem;
  Change: TItemChange);
begin
  Notebook.ActivePage := Item.Caption;
  CaptionBar.Caption := Item.Caption;
  { Set Pictures }
  if Assigned(PictureSmall) then begin
    TImageList(ListView.SmallImages).GetBitmap(Item.ImageIndex,
PictureSmall.Bitmap);
    CaptionBar.SmallPicture := PictureSmall;
  end;
  if Assigned(PictureLarge) then begin
    TImageList(ListView.LargeImages).GetIcon(Item.ImageIndex,
PictureLarge.Icon);
    CaptionBar.LargePicture := PictureLarge;
  end;
  {}
  case Item.Index of
    0: DS.DataSet := DMPhoneList.DSPeople.DataSet; // People
    1: DS.DataSet := DMPhoneList.DSPlaces.DataSet; // Places
  end;
end;
//------------------------------------------------------------------------------

 

Re:Events occurring after the FormDestroy event


In article <355E222D.B1C10...@mindspring.com>, "Edward J. Stembler"

Quote
<estem...@mindspring.com> writes:
>procedure TFormMain.FormDestroy(Sender: TObject);
>begin
>  Application.HelpCommand(HELP_QUIT, 0);
>  { Free References }
>  Rep.Free;
>  PictureSmall.Free;

PictureSmall := nil;

Quote
>  PictureLarge.Free;

PictureLarge ;= nil;

Quote
>end;

the "if Assigned(" checks to see if the pointer is nil, assuming if the pointer
is not nil that the object has been assigned. Delphi does not set pointers of
objects to nil when it frees them, unless they are in the Component array of an
object it is freeing.

So the "if Assigned(" thinks the object is still valid and tries to access it.

It's good programming practice to set all objects to nil that you free
yourself.

I am assuming that PictureSmall and PictureLarge are objects for which you have
NOT nominated an Owner when you created them.

If you have nominated an Owner when you created them, then you do not need to
explicitly free them. Delphi will free them before it frees the owner, and
because they are in the owner's componenst array, the pointers will be nilled.

Alan Lloyd
alangll...@oal.com

Re:Events occurring after the FormDestroy event


That fixed it (assigning to nil after freeing).  Thanks.

Quote
AlanGLLoyd wrote:
> In article <355E222D.B1C10...@mindspring.com>, "Edward J. Stembler"
> <estem...@mindspring.com> writes:

> >procedure TFormMain.FormDestroy(Sender: TObject);
> >begin
> >  Application.HelpCommand(HELP_QUIT, 0);
> >  { Free References }
> >  Rep.Free;
> >  PictureSmall.Free;

> PictureSmall := nil;

> >  PictureLarge.Free;

> PictureLarge ;= nil;

> >end;

> the "if Assigned(" checks to see if the pointer is nil, assuming if the pointer
> is not nil that the object has been assigned. Delphi does not set pointers of
> objects to nil when it frees them, unless they are in the Component array of an
> object it is freeing.

> So the "if Assigned(" thinks the object is still valid and tries to access it.

> It's good programming practice to set all objects to nil that you free
> yourself.

> I am assuming that PictureSmall and PictureLarge are objects for which you have
> NOT nominated an Owner when you created them.

> If you have nominated an Owner when you created them, then you do not need to
> explicitly free them. Delphi will free them before it frees the owner, and
> because they are in the owner's componenst array, the pointers will be nilled.

> Alan Lloyd
> alangll...@oal.com

Other Threads