Sign in Join

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

Mailing lists / fpc-devel / 2018-07

FreeInstance

11 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

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

Ryan Joseph

Looking at the FPC source now and it appears FreeInstance is a hidden method which is not called from the TObject destructor.

Where/how is this method called in the source? I’ve been in the debugger for over an hour and I still can’t find it.

Regards,
Ryan Joseph

Reply by email

Thorsten Engler
to Ryan Joseph

I don't think it's called anywhere in the source. It's called by the compiler after the destructor has finished. The same way that InitInstance is run before the constructor is called.

This way the memory for the object is already allocated before the first constructor is run (and not only after calling inherited and getting all the way to TObject) and it is only freed after the destructor has completed (so again, you aren't in limbo after calling inherited in the destructor).

Show quoted text 19 lines
-----Original Message----- From: fpc-devel On Behalf Of Ryan Joseph Sent: Wednesday, 1 August 2018 01:36 To: FPC developers' list Subject: [fpc-devel] FreeInstance Looking at the FPC source now and it appears FreeInstance is a hidden method which is not called from the TObject destructor. Where/how is this method called in the source? I’ve been in the debugger for over an hour and I still can’t find it. Regards, Ryan Joseph _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Ryan Joseph
to Thorsten Engler
On Jul 31, 2018, at 9:48 AM, Thorsten Engler wrote: I don't think it's called anywhere in the source. It's called by the compiler after the destructor has finished. The same way that InitInstance is run before the constructor is called.

then how does it get invoked then? there must be some node added somewhere but I can’t find it.

Regards,
Ryan Joseph

Reply by email

Ryan Joseph
to Ryan Joseph
On Jul 31, 2018, at 9:56 AM, Ryan Joseph wrote: then how does it get invoked then? there must be some node added somewhere but I can’t find it.

I’m still trying to find this with no luck. I suspect there’s a call node added when the compiler detects a destructor was called (maybe in ncal.pas or similar node unit) but I have no idea where. Any ideas?

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph: I’m still trying to find this with no luck. I suspect there’s a call node added when…

Ryan Joseph schrieb am Di., 31. Juli 2018,
22:29:

Show quoted text 12 lines
> On Jul 31, 2018, at 9:56 AM, Ryan Joseph wrote: > > then how does it get invoked then? there must be some node added somewhere but I can’t find it. I’m still trying to find this with no luck. I suspect there’s a call node added when the compiler detects a destructor was called (maybe in ncal.pas or similar node unit) but I have no idea where. Any ideas?

Search the compiler's source for the string 'FREEINSTANCE'; you'll find two locations, one in ngenutil and one in psub. The latter is the one you want.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Aug 1, 2018, at 9:17 AM, Sven Barth via fpc-devel wrote: Search the compiler's source for the string 'FREEINSTANCE'; you'll find two locations, one in ngenutil and one in psub. The latter is the one you want.

Yeah, this is the first place I looked but current_structdef is always nil so it never progresses past that point.

Is this test program not enough to get FreeInstance called?

program test;
var
	obj1: TObject;
begin
	obj1 := TObject.Create;
	obj1.Free;
end.

===========

    function generate_bodyexit_block:tnode;
      var
        srsym : tsym;
        para : tcallparanode;
        newstatement : tstatementnode;
        oldlocalswitches: tlocalswitches;
      begin
        result:=internalstatements(newstatement);
        if assigned(current_structdef) then
          begin
            { Don't test self and the vmt here. The reason is that  }
            { a constructor already checks whether these are valid  }
            { before. Further, in case of TThread the thread may    }
            { free the class instance right after AfterConstruction }
            { has been called, so it may no longer be valid (JM)    }
            oldlocalswitches:=current_settings.localswitches;
            current_settings.localswitches:=oldlocalswitches-[cs_check_object,cs_check_range];
            { a destructor needs a help procedure }
            if (current_procinfo.procdef.proctypeoption=potype_destructor) then
              begin
                if is_class(current_structdef) then
                  begin
                    srsym:=search_struct_member(current_structdef,'FREEINSTANCE');

Regards,
Ryan Joseph

Reply by email

Ben Grasset
to Ryan Joseph
On Wed, Aug 1, 2018 at 11:27 AM, Ryan Joseph
Yeah, this is the first place I looked but current_structdef is always

nil so it never progresses past that point.

Is this test program not enough to get FreeInstance called?

You need to declare a class, and give that class at least one method for current_structdef to ever not be 'll only specifically get to the FreeInstance part after that if it has a destructor.

Reply by email

Sven Barth
to Ryan Joseph: Yeah, this is the first place I looked but current_structdef is always nil so it never…

Ryan Joseph schrieb am Mi., 1. Aug. 2018,
17:28:

Show quoted text 55 lines
> On Aug 1, 2018, at 9:17 AM, Sven Barth via fpc-devel < > wrote: > > Search the compiler's source for the string 'FREEINSTANCE'; you'll find two locations, one in ngenutil and one in psub. The latter is the one you want. > Yeah, this is the first place I looked but current_structdef is always nil so it never progresses past that point. Is this test program not enough to get FreeInstance called? program test; var obj1: TObject; begin obj1 := TObject.Create; obj1.Free; end. =========== function generate_bodyexit_block:tnode; var srsym : tsym; para : tcallparanode; newstatement : tstatementnode; oldlocalswitches: tlocalswitches; begin result:=internalstatements(newstatement); if assigned(current_structdef) then begin { Don't test self and the vmt here. The reason is that } { a constructor already checks whether these are valid } { before. Further, in case of TThread the thread may } { free the class instance right after AfterConstruction } { has been called, so it may no longer be valid (JM) } oldlocalswitches:=current_settings.localswitches; current_settings.localswitches:=oldlocalswitches-[cs_check_object,cs_check_range]; { a destructor needs a help procedure } if (current_procinfo.procdef.proctypeoption=potype_destructor) then begin if is_class(current_structdef) then begin srsym:=search_struct_member(current_structdef,'FREEINSTANCE');

If you'd look at the code you quoted you'd see that this is only inserted *inside* a destructor (the check for potype_destructor; current_procinfo is the currently compiled routine). So, no, your code is not enough. You need to declare a class with a destructor, then the code would be entered.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Aug 1, 2018, at 3:28 PM, Sven Barth via fpc-devel wrote: If you'd look at the code you quoted you'd see that this is only inserted *inside* a destructor (the check for potype_destructor; current_procinfo is the currently compiled routine). So, no, your code is not enough. You need to declare a class with a destructor, then the code would be entered.

Now I see what’s happening! I would have caught this before but I had the class in another unit so it was compiled before I ran the debugger and I never got inside the destructor.

Thanks guys.

Regards,
Ryan Joseph

Reply by email