[fpc-devel] Reference counting interface objects

Adriaan van Os fpc at microbizz.nl
Thu Oct 16 15:02:55 CEST 2014


Jonas Maebe wrote:
> 
> On 16 Oct 2014, at 12:35, Adriaan van Os wrote:
> 
>> Now, it seems (correct me if I am wrong) that theEvent doesn't need to 
>> be manually released, because it has been declared as an OUT parameter 
>> rather than a VAR parameter. So, if this is true, this information is 
>> crucial when writing interface bindings.
> 
> Nothing ever needs to be manually released, regardless of whether it's a 
> VAR or OUT parameter. That's the whole point of automatic reference 
> counting)

I agree for pure Pascal code, where a parameter can be OUT or VAR and automatic release will work 
in both cases. However, I disagree for interfacing with external interfaces. It must be clear for 
the bindings-writer that VAR in the bindings instead of (what should have been) OUT can cause a 
memory leak. This is tricky enough that it deserves an explanation in the manual. For example, I 
think (from Windows MediaFoundation)

type
     IMFMediaEventGenerator = interface( IUnknown) ...
     ....
          function GetEvent( dwFlags: DWORD; OUT ppEvent: IMFMediaEvent): HResult; stdcall;

is correct, whereas

          function GetEvent( dwFlags: DWORD; VAR ppEvent: IMFMediaEvent): HResult; stdcall;

will leak memory.

> 
> Regarding the effects of the various qualifiers:
> * nothing (value): the reference count of the parameter is increased (I 
> forgot whether it's the caller or callee that does it) on entry and 
> decreased on exit
> * OUT: the reference count of the value that's passed in is decreased by 
> 1, and the variable that's passed into the procedure is initialized to 
> "empty" (nil, but that's an implementation detail)
> * VAR: nothing happens to the reference count. A reference to the 
> original variable is passed in, and changing it or reading it has 
> exactly the same effect as changing/reading the original variable.
> * CONST: this is the only tricky one. Again nothing happens to the 
> reference count, but because you can pass non-lvalues here. In 
> particular, you can pass a class implementing an interface rather than 
> the interface itself, which can cause the class to be freed 
> unexpectedly. See the example at 
> http://docwiki.embarcadero.com/RADStudio/XE7/en/Using_Reference_Counting . 
> The same can happen with functions returning a class instance passed to 
> a function expecting a CONST interface parameter. There is an open bug 
> report about adding a warning for it: 
> http://bugs.freepascal.org/view.php?id=19503

Thanks for the explanation. This clarifies things.

Regards,

Adriaan van Os




More information about the fpc-devel mailing list