I want special record that is have interface.
and, the interface has child interface and some class. so, need auto release. but, interface in record is already released.
need help, why reference count is missmatch ?
I try next code...
//--------------------------------------------------------------------
type
IIn = interface
procedure SetValue(v : string);
function AsString() : string;
function GetChild() : IIn;
end;
RIn = record
FIn : IIn;
procedure SetInterface(intf : IIn);
procedure SetValue(v : string);
function AsString() : string;
function GetChild() : RIn;
end;
TIn = class(TInterfacedObject, IIn)
private
FChild : IIn;
FValue : string;
public
procedure SetValue(v : string);
function AsString() : string;
function GetChild() : IIn;
end;
//--------------------------------------------------------------------
procedure RIn.SetInterface(intf : IIn);
begin
FIn := intf;
end;
function RIn.GetChild() : RIn;
var
childInterface : IIn;
begin
if FIn = nil then FIn := TIn.Create();
childInterface := FIn.GetChild();
Result.SetInterface( childInterface );
end;
procedure RIn.SetValue(v : string);
begin
if FIn = nil then FIn := TIn.Create();
FIn.SetValue(v);
end;
function RIn.AsString() : string;
begin
if FIn = nil then FIn := TIn.Create();
Result := FIn.AsString();
end;
function RIn.GetRefCnt() : integer;
begin
if FIn = nil then FIn := TIn.Create();
Result := FIn.GetRefCnt();
end;
procedure TIn.SetValue(v : string);
begin
FValue := v;
end;
function TIn.AsString() : string;
begin
Result := FValue;
end;
function TIn.GetChild() : IIn;
begin
if FChild = nil then FChild := TIn.Create();
Result := FChild;
end;
//--------------------------------------------------------------------
// global var
var
test : RIn;
// test procedure 1
procedure test1;
begin
test.GetChild().SetValue('test...');
end;
// test procedure 2
procedure test2;
begin
ShowMessage( test.GetChild().AsString ); <----- Error!! child interface is already released..
end;
It is Delphi 2009 reference counting bug. I modified your code a little to output reference counters:
program Bug2009;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
IIn = interface
procedure SetValue(v : string);
function AsString() : string;
function GetChild() : IIn;
end;
RIn = record
FIn : IIn;
procedure SetInterface(intf : IIn);
procedure SetValue(v : string);
function AsString() : string;
function GetChild() : RIn;
end;
TIn = class(TInterfacedObject, IIn)
private
FChild : IIn;
FValue : string;
public
procedure SetValue(v : string);
function AsString() : string;
function GetChild() : IIn;
end;
procedure RIn.SetInterface(intf : IIn);
begin
FIn := intf;
end;
function RIn.GetChild() : RIn;
var
childInterface : IIn;
begin
if FIn = nil then FIn := TIn.Create();
childInterface := FIn.GetChild();
Result.SetInterface( childInterface );
end;
procedure RIn.SetValue(v : string);
begin
if FIn = nil then FIn := TIn.Create();
FIn.SetValue(v);
end;
function RIn.AsString() : string;
begin
if FIn = nil then FIn := TIn.Create();
Result := FIn.AsString();
end;
procedure TIn.SetValue(v : string);
begin
FValue := v;
end;
function TIn.AsString() : string;
begin
Result := FValue;
end;
function TIn.GetChild() : IIn;
begin
if FChild = nil then FChild := TIn.Create();
Writeln(FChild._AddRef - 1);
FChild._Release;
Result := FChild;
end;
// global var
var
test : RIn;
// test procedure 1
procedure test1;
begin
test.GetChild().SetValue('test...');
end;
// test procedure 2
procedure test2;
begin
Writeln( test.GetChild().AsString ); // <----- Error!! child interface is already released..
end;
begin
try
test1;
test2;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
readln;
end.
The output (Delphi 2009) is
The same test on Delphi XE outputs
See different reference counter values
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With