Who would expect this to leak memory?
Who would expect this to leak memory?
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
IFoo = interface
procedure Bar;
end;
TFoo = class(TInterfacedObject, IFoo)
private
fProc: TProc;
public
constructor Create(const proc: TProc);
procedure Bar;
end;
constructor TFoo.Create(const proc: TProc);
begin
inherited Create;
fProc := proc;
end;
procedure TFoo.Bar;
begin
end;
procedure CheckException(const proc: TProc);
begin
try
proc();
except
//...
end;
end;
procedure Main;
var
foo: IFoo;
begin
foo := TFoo.Create(procedure begin end);
CheckException(procedure begin foo.Bar end);
end;
begin
ReportMemoryLeaksOnShutdown := True;
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
IFoo = interface
procedure Bar;
end;
TFoo = class(TInterfacedObject, IFoo)
private
fProc: TProc;
public
constructor Create(const proc: TProc);
procedure Bar;
end;
constructor TFoo.Create(const proc: TProc);
begin
inherited Create;
fProc := proc;
end;
procedure TFoo.Bar;
begin
end;
procedure CheckException(const proc: TProc);
begin
try
proc();
except
//...
end;
end;
procedure Main;
var
foo: IFoo;
begin
foo := TFoo.Create(procedure begin end);
CheckException(procedure begin foo.Bar end);
end;
begin
ReportMemoryLeaksOnShutdown := True;
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
well, never tried to use an Interface within an anonymous method?
ReplyDeleteIt is counted up for being part of the Anonymous method, but never counted down? Maybe "const" is part of the problem again, too?
I do.
ReplyDeletehttp://qc.embarcadero.com/wc/qcmain.aspx?d=101846
program AnonMethLeak;
{$APPTYPE CONSOLE}
uses
SysUtils;
procedure Test(a: TProc);
begin
end;
begin
ReportMemoryLeaksOnShutdown := True;
Test(procedure begin end);
end.
okay...surprised o.O
ReplyDeleteNope, Uwe. That is why I wrote the Main routine ;)
ReplyDeleteWe are facing a circular reference here because these 2 anonymous methods are internally implemented by the same class and thus share their RefCount.
TFoo keeps alive the first one and the second one keeps alive foo. If they were implemented by different instances their RefCount would go to 0.
As good as interfaces might be, the refcount in Delphi, in conjunction with circular references, can be a nightmare to debug.
ReplyDelete