Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I check whether an object reference is still valid?

I have an issues where I am trying to determine if a reference to an object is valid. But it seems to be returning strange results.

procedure TForm1.Button1Click(Sender: TObject);
  var form1 : TForm;
      ref2 : TControl;
begin
  form1 := TForm.Create(nil);
  form1.Name := 'CustomForm';
  form1.Parent := self; //Main Form

  form1.Show;

  ref2 := form1;
  showmessage(ref2.ClassName+' - '+ref2.Name+' - '+BoolToStr(ref2.visible,true));
  freeandnil(form1);
  showmessage(ref2.ClassName+' - '+ref2.Name+' - '+BoolToStr(ref2.visible,true));
end;

The first showmessage returns - "TForm - CustomForm - True" (Just like I would expect it to).

The second showmessage return - "TForm - - False". I was actually hoping for some kind of access violation that I could then trap and know that the reference isn't valid.

In my application I need to compile a list of random TForm descendants as they are created and then check later if they have gone away (or are not visible). Unfortunately it is a plugin based system so I can go change all of these Forms to post a "I'm done Message."

Would code like this be safe to use (assuming I actually am checking for access violations)? Does anybody have any ideas what is happening.

Thanks

like image 785
tmjac2 Avatar asked Jan 28 '10 15:01

tmjac2


2 Answers

The problem is that with a certain likelyhood the memory accessed is still reserved by the Delphi memory manager. In that case Windows does not generate any kind of access violation, because that memory belongs to you!

One possibility is to switch to a different Delphi memory manager which can detect the use of freed objects. FastMM4, for example, has several "memory hygiene" checks, which are very useful for debugging, but even then you won't catch all of these errors immediately.

You can download FastMM4 from SourceForge.

like image 54
Daniel Rikowski Avatar answered Sep 27 '22 17:09

Daniel Rikowski


Any TComponent (e.g. a TForm descendant) can register for notifications when other components are destroyed.

In your form, call FreeNotification(form) for each form that you wish to be notified of the destruction of. Then on the same form override the Notification() method. When any form (or other component) for which you have called FreeNotification() is destroyed, your Notification() method will be called with a Component parameter referencing the form and an Operation of opRemove.

If I've understood what it is you are trying to achieve, I think this should be enough information to devise an approach to do what you need.

like image 38
Deltics Avatar answered Sep 27 '22 19:09

Deltics