I recently came across (again) the Delphi compiler code-gen bug when passing an interface as const
leaks a reference.
This happens if your method is declared to pass an interface variable as const
, e.g.:
procedure Frob(const Grob: IGrobber);
and the fix is to simply remove the const
:
procedure Frob(Grob: IGrobber);
I understand that const
(and var
, and out
) allow you to pass items by reference. In the case of a structure this saves an argument copy; letting you instead simply pass the pointer to the item.
In the case of an Object
/Pointer
/Interface
there is no need to pass by reference, since it is a reference; it already will fit in a register.
In order to never have this problem again, i went on a crusade. I searched all my source trees for:
const [A-Za-z]+\: I[A-Z]
And i removed about 150 instances where i pass an interface as const.
But there are ones that i cannot change. The TWebBrowser
callback events are declared as:
OnDocumentComplete(Sender: TObject; const pDisp: IDispatch; var URL: OleVariant);
\___/
|
?
Have i gone too far? Have i done a bad thing?
Edit: Or, to phrase it in a less "based on opinion" style question: are there any serious down-sides to not passing an interface as const?
Bonus: When Delphi does not (always) increment a interface reference count they are violating The Rules of COM:
Reference-Counting Rules
Rule 1: AddRef must be called for every new copy of an interface pointer, and Release called for every destruction of an interface pointer, except where subsequent rules explicitly permit otherwise.
Rule 2: Special knowledge on the part of a piece of code of the relationships of the beginnings and the endings of the lifetimes of two or more copies of an interface pointer can allow AddRef/Release pairs to be omitted.
So while it may be an optimization that the compiler can take advantage of, it has to do it correctly so as to not violate the rules.