Почему действительно соединяют интерфейсом с реализациями на основе памяти утечки TComponent?

Этот код Delphi покажет утечку памяти для экземпляра TMyImplementation:

program LeakTest;

uses
  Classes;

type
  MyInterface = interface
  end;

  TMyImplementation = class(TComponent, MyInterface)
  end;

  TMyContainer = class(TObject)
  private
    FInt: MyInterface;
  public
    property Impl: MyInterface read FInt write FInt;
  end;

var
  C: TMyContainer;
begin
  ReportMemoryLeaksOnShutdown := True;

  C := TMyContainer.Create;
  C.Impl := TMyImplementation.Create(nil);
  C.Free;
end.

Если TComponent заменяется TInterfacedObject и конструктором, измененным для Создания (), утечка исчезает. Что отличается с TComponent здесь?

Большое спасибо за ответы. Подвести итог: это легко, но неправильно, для высказывания, "Если Вы используете интерфейсы они - считаемая ссылка, и следовательно они освобождены для Вас". - На самом деле любой класс, который реализует интерфейс, может нарушить это правило. (И не будет никакой подсказки компилятора или предупреждения быть показанными.)

18
задан mjn 2 February 2010 в 09:03
поделиться

3 ответа

Различия в реализации

  • TComponent._release не бесплатно ваш экземпляр.
  • TINTERFACESOBJECT._RELEASE делает бесплатное ваш экземпляр.

Возможно, кто-то может быть, но мой взять на себя так, это то, что TComponent не предназначен для использования в качестве ссылки, подсчитанного объекта, как мы обычно используют интерфейсы.

Реализация TComponent._release

function TComponent._Release: Integer;
begin
  if FVCLComObject = nil then
    Result := -1   // -1 indicates no reference counting is taking place
  else
    Result := IVCLComObject(FVCLComObject)._Release;
end;
28
ответ дан 30 November 2019 в 06:14
поделиться

Предполагается, что компонент должен быть принадлежен и уничтожен чем-то другим, как правило, является формой. В этом сценарии ссылочный счет не используется. Если вы проходите компонент в качестве ссылки на интерфейс, было бы очень неудачно, если бы он был уничтожен, когда метод возвращается.

Следовательно, отсчет ссылок в TComponent был удален.

6
ответ дан 30 November 2019 в 06:14
поделиться

Нет, нет лучшего способа сделать это. Однако я не думаю, что это имеет большое значение. Код уже упакован как повторно используемый метод. Если необходимо использовать его из нескольких отдельных классов, просто превратитесь в публичный статический метод в каком-нибудь служебном классе.

Как только вы это сделаете, для всех практических целей у вас будет удобный способ преобразования ab-массива объектов в массив классов. Другими словами, если вы уже внедрили определенный сервис в многоразовом пути, то вы эффективно расширили набор инструментов. Не имеет значения, что эта конкретная услуга не является частью «стандартной» JRE.

-121--4817695-

Насколько мне известно, ВЫ НЕ МОЖЕТЕ. CSS относится к стилю, а изображение src - к содержимому.

-121--1896641-

TComponent не реализует свои методы _AddRef и _Release так же, как и TInterfacedObject. Он откладывает отсчет ссылок на свое свойство VCLComObject , которое должно быть одним другим объектом с интерфейсом . Так как TComponent не подсчитывает ссылки, он не может определить, когда количество ссылок достигает нуля, поэтому он не освобождается.

Свойство VCLComObject содержит ссылку на интерфейс, которая должна реализовывать IVCLComObject . Если связанному с компонентом объекту VCLComObject было указано, что ему принадлежит компонент, то при достижении нулевого количества ссылок на этот интерфейс он уничтожит связанный с ним компонент. Ему сказали, что он владеет компонентом, вызвав его метод FreeOnRelease.

Все это предназначено для упрощения преобразования компонентов VCL в COM-объекты. Если это не ваша цель, то вы, вероятно, будете бороться с несколькими другими неожиданными аспектами дизайна на этом пути, так что вы, возможно, захотите пересмотреть мотивацию для того, чтобы ваши компоненты реализовывали интерфейсы в первую очередь.

20
ответ дан 30 November 2019 в 06:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: