2013-12-04 1 views
5

Если я реализую интерфейс в форме, такой как TMyForm = class(TForm, IMyInterface), будет ли объект свободен сам, когда на нем больше нет ссылок на интерфейс? Кажется, это не так, хотя я не мог понять, как подсчитывается ссылка TForm (если вообще). Меня беспокоит, что форма освобождается, когда ссылка на интерфейс выходит за пределы области видимости, но это, похоже, не происходит.Будет ли реализованная форма интерфейса свободной, если на ней больше нет ссылок?

Наверно, есть две части вопроса: во-первых, может ли быть неожиданно освобождена форма (реальный вопрос), а во-вторых, как формы подсчитываются.

+0

@TLama TForm происходит от TComponent, который реализует IInterface и IInterfaceComponentReference. TComponent реализует _AddRef и _Release, но они, похоже, только условно делают подсчет ссылок. – Alister

+0

@Alister: 'TComponent' отключает подсчет ссылок на себя, но будет выполнять подсчет ссылок на его свойство' VCLCOMObject', если оно назначено. –

+0

@ Алистер, извините, может быть, я неправильно понял ваш вопрос (прежде чем перечитывать его несколько раз), но я подумал, что вы спрашиваете, что произойдет, если вы добавите интерфейс (который будет реализован в классе 'TForm'). Если добавление этого интерфейса опасно как-то, и если это добавляет ссылку на форму. – TLama

ответ

12

TForm происходит от TComponent, который реализует _AddRef() и _Release() отключить подсчет ссылок на себя. Таким образом, любой интерфейс, реализованный любым классом потомков TComponent, например TForm, не будет освобождать его реализующий объект TComponent по умолчанию при освобождении интерфейса.

Однако, если IVCLComObject интерфейса присваивается TComponent.VCLCOMObject собственности, то TComponent будет делегировать подсчет ссылок на этот объект, так что объект может быть освобожден, если его счетчик ссылок падает до 0 (TComponent не увеличивает счетчик ссылок его IVCLCOMObject ссылка).

Это действительное для всех потомков TComponent, если они не осуществляют какой-либо собственный подсчет ссылок, переопределяя _AddRef() и _Release() вручную.

+0

Я больше беспокоюсь о том, что еще может установить VCLComObject. – Alister

+0

@Alister: 'TComponent.VCLCOMObject' устанавливается, если доступен' TComponent.ComObject', что действует только в том случае, если проект использует блок 'VCLCom' (иначе доступ к свойству' ComObject' приведет к возникновению исключения). –

+2

Другими словами: до тех пор, пока вы не выставляете свою форму каким-либо образом через COM-сервер, где подсчет ссылок кажется адекватным, мало шансов, что что-то установит VCLComObject без вашего вмешательства. –

0

Если вы реализуете интерфейс в форме, он может быть стоит добавить свой собственный

_Release as follows: 

    function _Release: Integer; stdcall; 

function TMyInterfacedForm._Release: Integer; 
begin 
    result:=-1; 
end; 

я обнаружил, что это было возможно, чтобы освободить форму с интерфейсом, а затем имеет _Release называют местным переменная вышла за рамки. Это может привести к нарушению прав доступа, так как реализация ТСотропепИ проверяет, является ли FVCLComObject установлено

if FVCLComObject = nil then 
    Result := -1 // -1 indicates no reference counting is taking place 
    else 
    Result := IVCLComObject(FVCLComObject)._Release; 

Поскольку на этой стадии, FVCLComobject не определен, раздражающее исключение A/V может произойти. При помощи проводки -1 это можно безопасно называть без исключений триггеров.

Смежные вопросы