[fpc-pascal] Delegate Interface class does not seem to be referenced counted
Tony Whyman
tony.whyman at mccallumwhyman.com
Thu Aug 18 12:25:25 CEST 2016
On 18/08/16 10:53, Graeme Geldenhuys wrote:
> I think you are getting confused between TObject and TInterfaceObject
> instances, and what is required from both.
No, the problem is that I could not find a way of achieving what I
wanted to achieve. That is ensuring that an interfaced object that used
a delegated interface would be reference counted and hence automatically
destroyed. The derived requirement is that I wanted neither a memory
leak nor the risk of a double free.
What I eventually discovered is that if an interfaced object is defined as:
TMyClass = class(TInterfacedObject, IMyInterface)
private
FMyInterface: IMyInterface;
property MyInterface: IMyInterface
read FMyInterface implements IMyInterface;
public
constructor Create(obj: TDelegateClass);
destructor Destroy; override;
end;
and then a TMyClass object is assigned to a variable of type
IMyInterface, the result is that the compiler ignores the TMyClass
object and references solely the object implementing IMyInterface i.e.
the TDelegateClass object. Intuitively, I had expected the reference to
be to the TMyClass Object as that was the one I assigned to the variable.
The result is that neither object gets freed automatically. The TMyClass
object does not get freed because it was ignored when the interface was
assigned and the TDelegateClass object was not freed because TMyClass
still has a reference to it.
On the other hand, if I assign a TMyClass object to a variable of type
IUnknown (which both TMyClass and TDelegateClass inherit), the compiler
now takes the interface from TMyClass and references this object. The
result is that at the end of the program both objects are automatically
destroyed.
I would certainly argue that this is confusing and counter-intuitive. I
can be persuaded either way that it is a bug or a feature, but I would
also argue that the intuitive outcome would be for the compiler to take
the reference to the TMyClass object in all cases.
Whatever view you take, the resulting behaviour needs to be carefully
documented as it is inviting memory leaks/double frees.
More information about the fpc-pascal
mailing list