FPC delphi mode behaviour does not honour Delphi documented object lifetimes
Original Reporter info from Mantis: jmd
-
Reporter name: Jared Davison
Original Reporter info from Mantis: jmd
- Reporter name: Jared Davison
Description:
Delphi defines the time of destruction of a reference counted object as: "the object is automatically destroyed when the last reference to it goes out of scope" (See http://docwiki.embarcadero.com/RADStudio/Seattle/en/Interface_References)
Steps to reproduce:
{
Call EnsureDelphiReferenceSemantics in the the following program to test the compiler behaviour matches Delphi in regards to when it destroys interfaced objects that have reached a reference count of 0. The program simply checks the order in which items are added to a string list to verify the behaviour is as expected.
}
unit CheckCompilerInterfaceRefCountSemantics;
interface
uses SysUtils;
type
ECompilerInterfaceSemanticsFailure = class(Exception);
procedure EnsureDelphiReferenceSemantics;
implementation
uses
Classes;
var
_sl : TStringList;
type
TAutoObj = class(TInterfacedObject, IInterface)
public
constructor Create;
destructor Destroy; override;
class function EnterAutoExit: IInterface;
end;
procedure Log(s: string);
begin
_sl.Add(s);
end;
constructor TAutoObj.Create;
begin
Log('0');
end;
destructor TAutoObj.Destroy;
begin
Log('2');
inherited;
end;
class function TAutoObj.EnterAutoExit: IInterface;
begin
Result := TAutoObj.Create() as IInterface;
end;
procedure DoEnterAutoExit;
begin
TAutoObj.EnterAutoExit;
Log('1');
end;
procedure VerifyResults;
begin
if not ((_sl.Count = 3) and (_sl[0] = '0') and (_sl[1] = '1') and (_sl[2] = '2')) then
begin
raise ECompilerInterfaceSemanticsFailure.Create('Object Pascal compiler does not support Delphi interface semantics where temporary varaiables are released at the end of scope. Please patch or use a different compiler.');
end;
end;
procedure EnsureDelphiReferenceSemantics;
begin
_sl := TStringList.Create;
try
DoEnterAutoExit;
VerifyResults;
finally
_sl.Free;
end;
end;
end.
Additional information:
Please refer to the attached patch "intf.patch".
Improve Delphi compatibility for lifetime of reference interfaced objects.
In Delphi, interface references are destroyed when last reference goes out of scope (Delphi emulation) (versus freepascal behaviour that is immediately when its no longer referenced. This Delphi behaviour is documented in Delphi "the object is automatically destroyed when the last reference to it goes out of scope. " http://docwiki.embarcadero.com/RADStudio/Seattle/en/Interface_References
This is important where object destruction has side effects whose timing of execution is of significance. This documented Delphi feature pattern is used in Delphi code to cause actions to happen automatically at the end of a scope.
With this patch Delphi mode compatibility turns this behaviour on, or it can be turned on via a compiler directive SCOPED_INTERFACE_DESTROY. (better names are welcome)
It would be helpful if the FPC documentation could be updated if this patch as accepted.
Also see:
http://www.freepascal.org/docs-html/ref/refse47.html
The chosen answer in: http://stackoverflow.com/questions/9592654/what-are-the-differences-between-implementation-of-interfaces-in-delphi-and-laza
Mantis conversion info:
- Mantis ID: 30409
- Version: 2.6.4
- Monitored by: » stocki (stocki), » @PascalDragon (Sven Barth)