Недавно я встретил (снова) ошибку кода-компилятора Delphi при передаче интерфейса как const
, утечка ссылки.
Это происходит, если ваш метод объявлен для передачи интерфейсной переменной как const
, например:
procedure Frob(const Grob: IGrobber);
и исправить это просто удалить const
:
procedure Frob(Grob: IGrobber);
Я понимаю, что const
(и var
и out
) позволяют передавать элементы по ссылке. В случае структуры это сохраняет копию аргумента; позволяя вместо этого просто передать указатель на элемент.
В случае Object
/Pointer
/Interface
нет необходимости передавать по ссылке, так как является ссылкой; он уже войдет в регистр.
Чтобы снова не иметь эту проблему, я отправился в крестовый поход. Я искал все мои исходные деревья для:
const [A-Za-z]+\: I[A-Z]
И я удалил около 150 экземпляров, где я передаю интерфейс как const.
Но есть те, которые я не могу изменить. Событие обратного вызова TWebBrowser
объявляется как:
OnDocumentComplete(Sender: TObject; const pDisp: IDispatch; var URL: OleVariant);
\___/
|
?
Неужели я зашел слишком далеко? Я сделал что-то плохое?
Изменить. Или, если фраза это в менее "основанном на мнении" вопросе стиля: есть ли серьезные нисходящие стороны, чтобы не передавать интерфейс как const?
Бонус: когда Delphi не (всегда) увеличивает счетчик ссылок интерфейса, они нарушают Правила COM:
Правила подсчета ссылок
Правило 1: AddRef должно быть вызвано для каждой новой копии указателя интерфейса, а Release - для каждого уничтожения указателя интерфейса, за исключением случаев, когда в последующих правилах явно разрешено иное.
Правило 2. Особые знания со стороны фрагмента кода отношений начала и окончания времен жизни двух или более копий указателя интерфейса могут позволить AddRef/Release.
Поэтому, хотя это может быть оптимизация, которую может использовать компилятор, она должна делать это правильно, чтобы не нарушать правила.