Sign in Join

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

Mailing lists / lazarus / 2011-04

Difference between FreeThenNil and FreeAndNil

24 messages · 9 people ·

Reply by email Subscribe to this list Your subscription

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

Luiz Americo Pereira Camara

After reading http://bugs.freepascal.org/view.php?id=19238 i wondered what's the reason to FreeThenNil procedure found in LCLProc.

What's the advantage over SysUtils FreeAndNil ?

procedure FreeThenNil(var obj);
begin
   if Pointer(obj)  nil then
   begin
     TObject(obj).Free;
     Pointer(obj) := nil;
   end;
end;
     procedure FreeAndNil(var obj);
       var
         temp: tobject;
       begin
         temp:=tobject(obj);
         pointer(obj):=nil;
         temp.free;
       end;

Luiz

Reply by email

Unknown author
to Alexander Klenin
Alexander Klenin wrote 9 lines
On Wed, Apr 27, 2011 at 13:30, Luiz Americo Pereira Camara wrote: > After reading http://bugs.freepascal.org/view.php?id=19238 i wondered what's > the reason to FreeThenNil procedure found in LCLProc. > > What's the advantage over SysUtils FreeAndNil ? That's a hack to work around the fact that some destructors may access the object being destroyed via the given pointer instead of directly.

Can you explain this ?

Because to my understanding the code does exactly the same.

Michael.

Reply by email

Alexander Klenin
to Unknown author
Show quoted text 7 lines
> That's a hack to work around the fact that some destructors may > access the object being destroyed via the given pointer instead of > directly. Can you explain this ? Because to my understanding the code does exactly the same.

No, these two procedures perform assignment and destruction in a different order -- even their names reflect that.

BTW, I think the check in FreeThenNil is redundant and should be removed.

Alexander S. Klenin

Reply by email

Unknown author
to Alexander Klenin: No, these two procedures perform assignment and destruction in a different order -- even…
Alexander Klenin wrote 11 lines
On Wed, Apr 27, 2011 at 18:15, wrote: >> That's a hack to work around the fact that some destructors may >> access the object being destroyed via the given pointer instead of >> directly. > > Can you explain this ? > > Because to my understanding the code does exactly the same. No, these two procedures perform assignment and destruction in a different order -- even their names reflect that.

Yes, I have seen that, but why is this relevant ?

I mean, if one does

   FreeAndNil(MyObject);

It really doesn't matter whether the reference MyObject is set to nil before or after the call to Free ?

Michael.

Reply by email

Unknown author
to Alexander Klenin: Sadly, it does, although I do not think it is a good programming practice. See my first…
Alexander Klenin wrote 10 lines
On Wed, Apr 27, 2011 at 18:46, wrote: > > I mean, if one does > ?FreeAndNil(MyObject); > It really doesn't matter whether the reference MyObject is set to nil before > or after the call to Free ? Sadly, it does, although I do not think it is a good programming practice. See my first mail in this thread ;-)

My collega explained to me what you meant (your original statement was not clear to me).

You're referring to cases like:

Var
   MyForm : TMyForm
destructor TMyForm.Destroy;
begin
   MyForm.Something;
end;

and then somewhere

   FreeAndNil(MyForm);

Which is simply wrong coding in the destructor.

I don't think you should provide for this. This is encouraging people to write bad code. They should get an error, and correct their code.

Michael.

Reply by email

Jürgen Hestermann
to Unknown author
I don't think you should provide for this. This is encouraging people to write bad code. They should get an error, and correct their code.

Agree.
I also don't understand why it is needed to manually free and set nil an object pointer if a destructor for the object exists which should do all this. This is like writing another destructor and makes object oriented programming (even more) useless.

Reply by email

Marc Weustink
to Jürgen Hestermann
J?rgen Hestermann wrote 11 lines
schrieb: > I don't think you should provide for this. This is encouraging people to > write bad code. They should get an error, and correct their code. Agree. I also don't understand why it is needed to manually free and set nil an object pointer if a destructor for the object exists which should do all this. This is like writing another destructor and makes object oriented programming (even more) useless.

On 15-1-2005 I had a heavy discussion with Mattias about this. IMO it was needed for a design flaw and he couldn't convince me why it was needed. I won't start that discussion again.

Marc

Reply by email

Alexander Klenin
to Jürgen Hestermann: Agree. I also don't understand why it is needed to manually free and set nil an object…
J?rgen Hestermann wrote
I also don't understand why it is needed to manually free and set nil an object pointer if a destructor for the object exists which should do all this. This is like writing another destructor and makes object oriented programming (even more) useless.

No, the destructor can not change the object pointer. That is the whole point.

Alexander S. Klenin

Reply by email

Alexander Klenin
to Unknown author: My collega explained to me what you meant (your original statement was not clear to me).…

2011/4/27 :

Which is simply wrong coding in the destructor. I don't think you should provide for this. This is encouraging people to write bad code. They should get an error, and correct their code.

Well, I have already said this is not a good practice, haven't I? But, it is not that easy to fix -- the calls are usually separated by many levels of nesting, including the message loop.

Alexander S. Klenin

Reply by email

Bernd
to Alexander Klenin: On Wed, Apr 27, 2011 at 19:19, J?rgen Hestermann No, the destructor can not change the…

2011/4/27 Alexander Klenin :

No, the destructor can not change the object pointer. That is the whole point.

It does not even know which or how many variables are pointing to it, does it? If this is the case then what does it matter which ones of them are set to nil before or after it is freed?

In FreeAndNil it is first freeing the object while the there still exists a reference to it (temp). But the object does not know about temp or var obj anyways and has no reference to any of them (where should it have leaned about them in the first place?), or does it?

So IMHO this pocedure is essentially doing exactly the same as the FreeThenNil procedure. At least that is how I understand it.

Reply by email

Unknown author
to Alexander Klenin: 2011/4/27 : Well, I have already said this is not a good practice, haven't I? But, it is…
Alexander Klenin wrote 9 lines
2011/4/27 : > Which is simply wrong coding in the destructor. > > I don't think you should provide for this. This is encouraging people to > write bad code. They should get an error, and correct their code. Well, I have already said this is not a good practice, haven't I? But, it is not that easy to fix -- the calls are usually separated by many levels of nesting, including the message loop.

I would like to see a non-trivial example of this.

Even if you can produce one (which I doubt), it doesn't change the fact that it is wrong coding.

Michael.

Reply by email

Graeme Geldenhuys
to Unknown author: My collega explained to me what you meant (your original statement was not clear to me).…

2011/4/27 :

Show quoted text 12 lines
begin ?MyForm.Something; end; and then somewhere ?FreeAndNil(MyForm); Which is simply wrong coding in the destructor. I don't think you should provide for this. This is encouraging people to write bad code. They should get an error, and correct their code.

+1
That is just bad coding. Fix the problem at the source, in stead of simply offering bandaids to encourage the developer to continue such bad practices.

Regards, ? - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net

Reply by email

Unknown author
to Alexander Klenin
Alexander Klenin wrote 7 lines
On Wed, Apr 27, 2011 at 21:20, wrote: > I would like to see a non-trivial example of this. > > Even if you can produce one (which I doubt), it doesn't change the fact that > it is wrong coding. http://bugs.freepascal.org/view.php?id=16035

But what does this have to do with the problem you mention in FreeAndNil ?

It's rebuilding a component tree, while part of the tree is still being destroyed. That this will go wrong seems logical to me, but irrelevant to FreeAndNil.

Michael.

Reply by email

Alexander Klenin
to Unknown author
Show quoted text 7 lines
> http://bugs.freepascal.org/view.php?id=16035 But what does this have to do with the problem you mention in FreeAndNil ? It's rebuilding a component tree, while part of the tree is still being destroyed. That this will go wrong seems logical to me, but irrelevant to FreeAndNil.

As you can see from the linked discussion,
currently implemented workaround involves FreeAndNil. I can imagine a similar bug which might require FreeThenNil instead.

Alexander S. Klenin

Reply by email

Unknown author
to Alexander Klenin
Alexander Klenin wrote 12 lines
On Wed, Apr 27, 2011 at 21:53, wrote: >> http://bugs.freepascal.org/view.php?id=16035 > > But what does this have to do with the problem you mention in FreeAndNil ? > > It's rebuilding a component tree, while part of the tree is still being > destroyed. That this will go wrong seems logical to me, but irrelevant to > FreeAndNil. As you can see from the linked discussion, currently implemented workaround involves FreeAndNil. I can imagine a similar bug which might require FreeThenNil instead.

I didn't see any linked discussion in the indicated page.

All I can conclude from this page is that there is a bug in TAChart, most likely returning children in GetChildren, which are in fact no longer there. But that is just guesswork, and still I fail to see the link with FreeAndNil.

If I see things in mails like like
"This code is so complicated, I can not understand what is going on." Then I automatically think "Badly written code" and therefore 'error-prone'.

But never mind.

Michael.

Reply by email

Alexander Klenin
to Unknown author
Show quoted text 5 lines
> As you can see from the linked discussion, > currently implemented workaround involves FreeAndNil. > I can imagine a similar bug which might require FreeThenNil instead. I didn't see any linked discussion in the indicated page.

If you scroll down a bit, you will see a single note, pointing to http://lists.lazarus.freepascal.org/pipermail/lazarus/2010-April/051023.html

If I see things in mails like like "This code is so complicated, I can not understand what is going on." Then I automatically think "Badly written code" and therefore 'error-prone'.

I agree and even I tried to refactor it -- but my work was rejected by core developers.

Alexander S. Klenin

Reply by email

Unknown author
to Alexander Klenin
Alexander Klenin wrote 9 lines
On Wed, Apr 27, 2011 at 22:18, wrote: >> As you can see from the linked discussion, >> currently implemented workaround involves FreeAndNil. >> I can imagine a similar bug which might require FreeThenNil instead. > > I didn't see any linked discussion in the indicated page. If you scroll down a bit, you will see a single note, pointing to http://lists.lazarus.freepascal.org/pipermail/lazarus/2010-April/051023.html

I saw that, where do you think I got the quote from ? :-)

Show quoted text 7 lines
> If I see things in mails like like > "This code is so complicated, I can not understand what is going on." > Then I automatically think "Badly written code" and therefore 'error-prone'. I agree and even I tried to refactor it -- but my work was rejected by core developers.

Ah? Strange. Maybe they wanted to promote FreeThenNil ;-)

Michael.

Reply by email

Graeme Geldenhuys
to Unknown author: But what does this have to do with the problem you mention in FreeAndNil ? It's…
Show quoted text 11 lines
On Wed, 27 Apr 2011, Alexander Klenin wrote: http://bugs.freepascal.org/view.php?id=16035 But what does this have to do with the problem you mention in FreeAndNil ? From that bug report it looks like a bug in TAChart, not in

FreeAndNil(). I have written a crap load of components in my time, including composite components, and never had a problem with freeing children or subcomponents. You just need to do it in the right order, and obviously not reference something that is already free'd.

regards,
Graeme

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net

Reply by email

Alexander Klenin
to Graeme Geldenhuys
Graeme Geldenhuys wrote 7 lines
>From that bug report it looks like a bug in TAChart, not in FreeAndNil(). I have written a crap load of components in my time, including composite components, and never had a problem with freeing children or subcomponents. You just need to do it in the right order, and obviously not reference something that is already free'd.

That is quite possible, but neither me nor Martin was unable to find it. I'd appreciate any specific insight if you have it.

Alexander S. Klenin

Reply by email

Florian Klämpfl
to Alexander Klenin
Alexander Klenin wrote 13 lines
On Thu, Apr 28, 2011 at 02:14, Graeme Geldenhuys wrote: > > >From that bug report it looks like a bug in TAChart, not in > FreeAndNil(). I have written a crap load of components in my time, > including composite components, and never had a problem with freeing > children or subcomponents. You just need to do it in the right order, > and obviously not reference something that is already free'd. > That is quite possible, but neither me nor Martin was unable to find it. I'd appreciate any specific insight if you have it.

Did you run the code with valgrind or using a heaptrc unit compiled with -dFPC_HEAPTRC_EXTRA?

Reply by email

Mattias Gaertner
to Alexander Klenin: On Thu, Apr 28, 2011 at 02:14, Graeme Geldenhuys That is quite possible, but neither me…

Alexander Klenin hat am 27. April 2011 um 18:46 geschrieben:

Show quoted text 11 lines
On Thu, Apr 28, 2011 at 02:14, Graeme Geldenhuys wrote: > > >From that bug report it looks like a bug in TAChart, not in > FreeAndNil(). I have written a crap load of components in my time, > including composite components, and never had a problem with freeing > children or subcomponents. You just need to do it in the right order, > and obviously not reference something that is already free'd.> >>? That is quite possible, but neither me nor Martin was unable to find it. I'd appreciate any specific insight if you have it.

FreeThenNil is useful for variables like 'Application', which destructor triggers complex things and/or when the variable is used at a lot of places. During the destruction Application is still valid, so that all components can shut down cleanly. For example they can unregister their handlers. ?
But FreeThenNil is more limited than FreeAndNil. For example?you can not use it with multithreading, because of the small step between freeing the memory and setting the variable to nil.
?
?
Mattias
?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110427/51a770ae/attachment-0001.html>

Reply by email