Recent

Author Topic: Why is FreeAndNil implemented "backwards", exactly?  (Read 10513 times)

Paulo França Lacerda

  • New Member
  • *
  • Posts: 44
    • BlaisePoint Informática
Re: Why is FreeAndNil implemented "backwards", exactly?
« Reply #15 on: October 03, 2016, 08:51:42 pm »
@Patulinu - You should not raise exception if passed object is nil. It is regular situation to call FreeAndNil on nil object.
Indeed.
Lazarus 1.6.0.4 on FreePascal 3.0
Windows 7 32-bit

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7504
Re: Why is FreeAndNil implemented "backwards", exactly?
« Reply #16 on: October 03, 2016, 09:15:27 pm »
I get that this is probably the way it was written in Delphi, and so it was just brought over to FPC that way, but it seems somewhat "dangerous". Since the "obj" parameter is typecasted to a pointer and then set to nil BEFORE calling Free on itself, doesn't this make it possible that it won't even exist when it goes to call Free?

That's what the pointer() typecast is for, to circumvent possible special behaviour (like decref) tied to tobject (even if default there is none).

If you do it the other way, the incoming "obj" reference points to a already deallocated object for a while (though I assume strictly there should be some fencing between the assignment and the free)

Paulo França Lacerda

  • New Member
  • *
  • Posts: 44
    • BlaisePoint Informática
Re: Why is FreeAndNil implemented "backwards", exactly?
« Reply #17 on: October 03, 2016, 09:26:16 pm »
Oops... I get a false-positive here when passing a pointer:
.
Code: Pascal  [Select]
  1.   if O is TObject then...   // this works with FPC, but generates a false-positive under Delphi.
.
In my tests, only the following works as expected (both under FPC and Delphi):

Code: Pascal  [Select]
  1. if O.InheritsFrom(TObject)...
« Last Edit: October 04, 2016, 04:01:03 am by Paulo França Lacerda (patulinu) »
Lazarus 1.6.0.4 on FreePascal 3.0
Windows 7 32-bit

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Why is FreeAndNil implemented "backwards", exactly?
« Reply #18 on: October 05, 2016, 09:23:29 pm »
Just 1 note on the topic that is good to know. Don't use global vars inside class that refer to same object you are about to destroy.
Code: Pascal  [Select]
  1. type
  2.   TTestClass = class
  3.     n: integer;
  4.     procedure DoSomething;
  5.     destructor Destroy; override;
  6.   end;
  7.  
  8.   TForm1 = class(TForm)
  9.     Button1: TButton;
  10.     procedure Button1Click(Sender: TObject);
  11.   private
  12.   public
  13.   end;
  14.  
  15. var
  16.   Form1: TForm1;
  17.   tc: TTestClass;
  18.  
  19. implementation
  20.  
  21. {$R *.lfm}
  22.  
  23. procedure TTestClass.DoSomething;
  24. begin
  25.   form1.Caption:=inttostr(n);
  26. end;
  27.  
  28. destructor TTestClass.Destroy;
  29. begin
  30.   // normally without "tc."
  31.   tc.DoSomething;
  32.   inherited Destroy;
  33. end;
  34.  
  35. procedure TForm1.Button1Click(Sender: TObject);
  36. begin
  37.   tc:=TTestClass.Create;
  38.   FreeAndNil(tc); // Sigsegv!
  39.   //tc.Free; tc:=nil; // This sequence works
  40. end;

totya

  • Hero Member
  • *****
  • Posts: 577
Re: Why is FreeAndNil implemented "backwards", exactly?
« Reply #19 on: October 05, 2016, 10:25:05 pm »
Hi!

I didn't get sigsev with your demo. Otherwise... you shouldn't use FreeAndNil in that way, the right way is long time ago:

Code: Pascal  [Select]
  1. if Assigned(SampleObject) then
  2.    FreeAndNil(SampleObject);

But it need too (long time ago), when you create object:

Code: Pascal  [Select]
  1. SampleObject:= nil;
  2. SampleObject:= TSampleObject.Create;
  3.  

and then you can test:

Code: Pascal  [Select]
  1. if Assigned(SampleObject) then

Thaddy

  • Hero Member
  • *****
  • Posts: 9184
Re: Why is FreeAndNil implemented "backwards", exactly?
« Reply #20 on: October 10, 2016, 02:44:37 pm »
Oops... I get a false-positive here when passing a pointer:
.
Code: Pascal  [Select]
  1.   if O is TObject then...   // this works with FPC, but generates a false-positive under Delphi.

WHICH Delphi version, because that is valid code and I usually test at least D7 and XE2.
Btw: You did not ask for Delphi compatibility.....
also related to equus asinus.

Paulo França Lacerda

  • New Member
  • *
  • Posts: 44
    • BlaisePoint Informática
Re: Why is FreeAndNil implemented "backwards", exactly?
« Reply #21 on: October 15, 2016, 09:11:54 pm »
Oops... I get a false-positive here when passing a pointer:
.
Code: Pascal  [Select]
  1.   if O is TObject then...   // this works with FPC, but generates a false-positive under Delphi.

WHICH Delphi version, because that is valid code and I usually test at least D7 and XE2.
Delphi 7, and it's unstable. Sometimes it generates the false-positive, sometimes it works as with FPC.
« Last Edit: October 15, 2016, 09:13:57 pm by Paulo França Lacerda (patulinu) »
Lazarus 1.6.0.4 on FreePascal 3.0
Windows 7 32-bit