Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting allocation address of an object in Delphi 7

I have the following code sequence:

program OverrideAfterConstructionEtc;

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes;

type

TA = class( TInterfacedObject)
public
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
protected
FDummyData: array[ 1 .. 1000 ] of longint;
end;

{ TA }

procedure TA.AfterConstruction;
var
    selfPtr: Pointer;
    selfInt: Integer;
    selfStr: string;
    size: Integer;
begin
    inherited AfterConstruction;
    selfPtr := Addr( self );
    selfInt := Integer( selfPtr );
    selfStr := IntToHex( selfInt, 8 );

    size := TA.InstanceSize;
    WriteLn( 'TA instance allocated at 0x', selfStr );
    WriteLn( 'TA size is ', size );


end;

procedure TA.BeforeDestruction;
var
    selfPtr: Pointer;
    selfInt: Integer;
    selfStr: string;

    size: Integer;

begin

    selfPtr := Addr( self );
    selfInt := Integer( selfPtr );
    selfStr := IntToHex( selfInt, 8 );

    WriteLn( 'Preparing to destroy TA instance allocated at 0x', selfStr );

    size := TA.InstanceSize;
    WriteLn( 'TA size is ', size );

    inherited BeforeDestruction;
end;

const
    maxDummy = 1000;
var
    a: TA;
    dummy: TList;
    iter : integer;

    dummies: array [ 1 .. maxDummy ] of TList;
begin

    // Simulate a set of allocations.

    for iter := 1 to maxDummy do
    begin
        dummy := TList.Create;
        dummies[ iter ] := dummy;
    end;

    // Allocate the object we want to track.
    a := TA.Create;

    // Release the simulated allocations.
    for iter := 1 to maxDummy do
    begin
        dummy := dummies[ iter ];
        dummies[ iter ] := nil;
        FreeAndNil( dummy );
    end;



    // Release the tracked object.

    FreeAndNil( a );

end.

The output of the code is:

  • TA instance allocated at 0x0012FF88
  • TA size is 4012 Preparing to destroy
  • TA instance allocated at 0x0012FF80
  • TA size is 4012

I do not understand the "self" difference. Can you give me a hint? I would have expected the printed values to be the same.

like image 204
Dan Avatar asked Nov 28 '22 22:11

Dan


1 Answers

Self in an instance method is an implicit argument and is a reference to the instance that received the method call. It is implemented as a pointer.

The Addr standard procedure is the same as the @ operator; it takes the address of the location passed to it. When you apply Addr to Self, you are getting the address of the parameter location, not the address of the instance. This parameter location is allocated on the stack, as it only needs to exist while the method call is active; when the method call returns, there is no longer any need for the space for the Self parameter; it gets released, implicitly, by the CPU's stack pointer moving back to whatever it was before the method was called.

The reason why the Self parameter may be at different locations in different invocations of methods on the same instance is because there may be more or less data on the stack at the time of the call. For example, the Self parameter will be allocated differently if the method call sequence looks like A -> B -> C versus A -> C, because the stack frame for B needs to be stored in between the stack frames for A and C. The stack frame is where the parameters and locals associated with any given invocation of a method are allocated.

like image 136
Barry Kelly Avatar answered Dec 09 '22 15:12

Barry Kelly