In some part of my application, I have the situation where I receive an interface which I know to be an object, albeit I don't know the exact class. I have to store that object in an interface-type variable.
Eventually, I might receive another instance of that type, and the first one must be discarded and replaced with the new one. For that, I need to free the memory that interfaced object uses (my interface provides an AsObject method so I can use the TObject methods on it). My problem is, when I want to assign "nil" to that variable again, I get an access violation.
I wrote a small program that reproduces my situation. I post it here to clarify the situation.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes;
type
ISomeInterface = interface
function SomeFunction : String;
function AsObject : TObject;
end;
TSomeClass = class(TComponent, ISomeInterface)
public
called : Integer;
function SomeFunction : String;
function AsObject : TObject;
end;
var
SomeInterface : ISomeInterface;
i : Integer;
function TSomeClass.SomeFunction : String;
begin
Result := 'SomeFunction called!';
end;
function TSomeClass.AsObject : TObject;
begin
Result := Self;
end;
begin
try
SomeInterface := nil;
for i := 1 to 10 do
begin
if SomeInterface <> nil then
begin
SomeInterface.AsObject.Free;
SomeInterface := nil; // <-- Access Violation occurs here
end;
SomeInterface := TSomeClass.Create(nil);
SomeInterface.SomeFunction; // <-- if commented, Access
// Violation does not occur
end;
except on e : Exception do
WriteLn(e.Message);
end;
end.
So the question is: how can I free that object correctly?
TComponent
does not use reference counting;AddRef
andRelease
return -1 – Expiate