[fpc-devel] Interface scope incompatibility with Delphi

Dimitri Smits smitco at telenet.be
Fri Nov 12 00:46:43 CET 2010


ok, answering my own mail after a small test below

----- "Dimitri Smits" <smitco at telenet.be> schreef:

> what I DON'T do is use it like in your example, Graeme. I always
> assign the result to a local variable, which goes out of scope in an
> implicit finally block at method-exit. Haven't tried if this does
> (not) work in fpc though.
> 

tested with following program and 2.4.0 (can someone verify on trunk)

it gives somewhat the desired result, but not completely. This IS a bug, I believe.

the expected behaviour is the next output:
  Entering: DoSomething 1
  Entering: DoSomething 2
  random message 1
  random message 2
  Exiting: DoSomething 2
  Exiting: DoSomething 1

but I got this output:
  Entering: DoSomething 1
  Entering: DoSomething 2
  random message 1
  random message 2
  Exiting: DoSomething 1
  Exiting: DoSomething 2

it seems that the stackvariables are NOT unloaded in the correct order (ie: reverse order of declaration).
It shouldn't matter in what order you fill them, but in the order they are declared. (like good practice in constructor vs destructor, but then in stack variables setup/cleanup)

---8<-----------8<-----------8<-----------8<-----------8<-----------
program project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes,
  SysUtils
  { you can add units after this };

{$R *.res}

type

  { TWriteLog }

  TWriteLog=class(TInterfacedObject)
  private
    FLogMessage: String;
  public
    constructor Create(str:string); overload;
    destructor Destroy; override;
  end;

{ TWriteLog }

constructor TWriteLog.Create(str: string);
begin
  inherited Create;
  FLogMessage := str;
  writeln(Format('Entering: %s', [ FLogMessage ]));
end;

destructor TWriteLog.Destroy;
begin
  writeln(Format('Exiting: %s', [ FLogMessage ]));
  inherited Destroy;
end;

procedure DoSomething;
var logMsg1, logMsg2: IInterface;
begin
  logMsg1 := TWriteLog.Create('DoSomething 1');
  logMsg2 := TWriteLog.Create('DoSomething 2');
  writeln('random message 1');
  writeln('random message 2');
end;

begin
  DoSomething;
  readln;
end.
---8<-----------8<-----------8<-----------8<-----------8<-----------

mind you, you could explicitly nillify one of the logMsg variables to force order as well.
Usually this is being used by our company for things like Screen.Cursor replacements and making sure that any unforseen errors in additional call(stacks) are handled without cluttering everything up with additional try/finally blocks.

other stuff we used this trick for includes 'DataSet.DisableControls', profiling/timing and transactionmanagment to name a few.

oh, and by the way: I get 2 warnings that the logMsg variables are assigned but not being used. This is too strict for tag-interfaces, as they actually are used due to assignment and ref-counting.

should I file (2/a) bug report(s)? or is there no point in doing so since they won't be fixed either?

kind regards,
Dimitri Smits



More information about the fpc-devel mailing list