Discussion:
FreeInstance
(too old to reply)
Ryan Joseph
2018-07-31 15:36:18 UTC
Permalink
Raw Message
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 - fpc-***@lists.freepascal.org
http://lists.freepascal.o
Thorsten Engler
2018-07-31 15:48:01 UTC
Permalink
Raw Message
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).

> -----Original Message-----
> From: fpc-devel <fpc-devel-***@lists.freepascal.org> On Behalf
> Of Ryan Joseph
> Sent: Wednesday, 1 August 2018 01:36
> To: FPC developers' list <fpc-***@lists.freepascal.org>
> 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 - fpc-***@lists.freepascal.org
> http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lis
Ryan Joseph
2018-07-31 15:56:54 UTC
Permalink
Raw Message
> On Jul 31, 2018, at 9:48 AM, Thorsten Engler <***@gmx.net> 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

_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.fre
Ryan Joseph
2018-07-31 20:29:21 UTC
Permalink
Raw Message
> On Jul 31, 2018, at 9:56 AM, Ryan Joseph <***@thealchemistguild.com> 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

_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/lis
Sven Barth via fpc-devel
2018-08-01 15:17:07 UTC
Permalink
Raw Message
Ryan Joseph <***@thealchemistguild.com> schrieb am Di., 31. Juli 2018,
22:29:

>
>
> > On Jul 31, 2018, at 9:56 AM, Ryan Joseph <***@thealchemistguild.com>
> 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

>
Ryan Joseph
2018-08-01 15:27:45 UTC
Permalink
Raw Message
> On Aug 1, 2018, at 9:17 AM, Sven Barth via fpc-devel <fpc-***@lists.freepascal.org> 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

_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin
Sven Barth via fpc-devel
2018-08-01 21:28:12 UTC
Permalink
Raw Message
Ryan Joseph <***@thealchemistguild.com> schrieb am Mi., 1. Aug. 2018,
17:28:

>
>
> > On Aug 1, 2018, at 9:17 AM, Sven Barth via fpc-devel <
> fpc-***@lists.freepascal.org> 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

>
Ryan Joseph
2018-08-01 22:21:25 UTC
Permalink
Raw Message
> On Aug 1, 2018, at 3:28 PM, Sven Barth via fpc-devel <fpc-***@lists.freepascal.org> 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

_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.free
Ben Grasset
2018-08-01 16:04:19 UTC
Permalink
Raw Message
> On Wed, Aug 1, 2018 at 11:27 AM, Ryan Joseph <***@thealchemistguild.com>
wrote:
> 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 nil at all. You'll only specifically get
to the FreeInstance part after that if it has a destructor.
Ben Grasset
2018-08-01 16:11:00 UTC
Permalink
Raw Message
Forgot to mention a record or object with at least one method will get to
the first part also, but never the FreeInstance part as they can never have
destructors.
Ben Grasset
2018-08-01 13:06:01 UTC
Permalink
Raw Message
> I’m still trying to find this with no luck.

Doing a quick search for the word "freeinstance" in the compiler source
shows two places where it looks for a member function with that name in the
global "current_structdef" variable. I'm fairly certain the one you're
looking for is in a function called "generate_bodyexit_block" at line 587
of psub.pas.

https://github.com/graemeg/freepascal/blob/master/compiler/psub.pas#L587
Loading...