Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.10.03;
Скачать: CL | DM;

Вниз

TInterfacedObject и reference counting   Найти похожие ветки 

 
qube ©   (2002-09-19 16:42) [0]

Сравнительно недавно узнал о дивных возможностях (subj). Наконец-то не надо заботиться об освобождении объектов. Вопрос старым опытным волкам: есть ли какие подводные камни и случаи, когда лучше не пользоваться этим механизмом?


 
Digitman ©   (2002-09-19 17:11) [1]


> Наконец-то не надо заботиться об освобождении объектов



Это кто тебе такое сказал ? Да, появляются определенные новые возможности, но это отнюдь не говорит о том, что отныне ты волен не обращать никакого внимания на логику распределения памяти под объекты !

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



 
qube ©   (2002-09-20 10:14) [2]

Ну, допустим, в хелпе есть пример ситуации, когда объект освобждается раньше, чем следовало. А может быть ситуация, что программа отработает, а какие-то объекты останутся в памяти?


 
Digitman ©   (2002-09-20 10:24) [3]


> А может быть ситуация, что программа отработает, а какие-то
> объекты останутся в памяти?


Если программа "правильная" - нет.


 
Внук ©   (2002-09-20 10:25) [4]

>>qube © (20.09.02 10:14)
После того, как процесс уничтожается, ничего не остается в памяти, поскольку уничтожается виртуальное адресное пространство процесса, а все описатели объектов исполнительной системы и ядра, используемые этим процессом, закрываются. Главная задача по большому счету - это чтобы в процессе работы не происходило постоянного увеличения захваченных ресурсов. Хотя, по хорошему, за собой всегда убирать надо :)


 
qube ©   (2002-09-20 10:55) [5]


> Digitman © (20.09.02 10:24)
> Если программа "правильная" - нет.


Об этом и вопрос. Что можно сделать неправильно. Как, к примеру, устроить утечку памяти?


 
vedmed ©   (2002-09-20 12:06) [6]

Одна из основных проблемм - циклические ссылки. Пример:

IABC = interface
function GetA: IABC;
procedure SetA(aValue: IABC);
property A: IABC read GetA write SetA;
end;

TABC = class(TInterfacedObject, IABC)
private
fA: IABC;
protected
function GetA: IABC;
procedure SetA(aValue: IABC);
public

published

end;

...
function TABC.GetA: IABC;
begin
Result := fA;
end;

procedure TABC.SetA(aValue: IABC);
begin
fA := aValue;
end;

...
procedure TForm1.Button1Click(Sender: TObject);
var
a: IABC;
begin
a := TABC.Create;
a.A := a;
end;

при выходе из процедуры TForm1.Button1Click объект "a" не уничтожается


 
qube ©   (2002-09-20 12:12) [7]

Спасибо.

Хотя мне пока трудно представить, где реально мне понадобились бы такие циклические ссылки.


 
vedmed ©   (2002-09-20 12:38) [8]

Это просто пример, показывающий возможные проблемы, когда один объект хранит ссылки на другой.


 
Digitman ©   (2002-09-20 13:06) [9]

Давай, приводи конкретный пример, в котором ты сомневаешься.
Разберем, что там к чему, как работает и к каким (ожидаемым и неожиданным) результатам приводит ...


 
qube ©   (2002-09-20 13:59) [10]

Ну, к примеру.

TSomeComplexClass = class
...
function FindSomething: TSomething;
..
end;

Хочется, чтобы клиентам класса TSomeComplexClass не надо было заниматься освобождением объектов, которые возвращает FindSomething. Решает ли проблему замена типа возвращаемого значения на ISomething.


 
Digitman ©   (2002-09-20 14:21) [11]

это зависит от того, где и как клиент объект SomeComplexClass будет хранить и использовать ссылку на ISomething, полученную в результате вызова SomeComplexClass.FindSomething().

Снова - приведи конкретный пример декларации переменной типа ISomething и код вызова метода, инициализирующего эту переменную и работающего с ней вполоть до завершения


 
qube ©   (2002-09-20 14:33) [12]

Чувствую, что ерунду справшиваю, но раз уж начал.
Вся каша заварена ради того, чтобы пользоваться классом TSomeComplexClass было максимально удобно.

Можно так:

procedure SomeProc;
var
s: ISomething;
....
s := ComplexObject.FindSomething;
s.DoSomething;
end;

Или так:

procedure SomeProc;
var
t: TSomeType;
....
ComplexObject.FindSomething.DoSomething;
t := ComplexObject.FindSomething.SomeProp;
end;


 
Digitman ©   (2002-09-20 14:47) [13]

В обоих случаях - все корректно. Но здесь не рассматривается творящееся в теле самого FindSomething. А это - тоже важно.


 
Старый Паскалист   (2002-09-20 14:52) [14]

FindSomething подразумевает создание нового объекта или
поиск существующего (или и то и другое вместе)?


 
qube ©   (2002-09-20 14:56) [15]

В принципе, может создавать, а то и проблемы бы не было


 
Digitman ©   (2002-09-20 15:08) [16]

если в теле FindSomething при генерации результата делается примерно следующее :

begin
..
Result := TSomething.Create(..) [as ISomething]
end;

то - все коррекно.



 
qube ©   (2002-09-20 15:12) [17]

Всем спасибо!
Если возникнут еще какие-то ворпосы по ходу, буду знать, к кому обращаться.


 
Старый Паскалист   (2002-09-20 15:13) [18]

Всё от задачи зависит.

Может быть такая логика:
FindSomething может возвращать просто объект, он будет храниться
в каком-либо списке ComplexObject"a, как бы кэшироваться, чтобы второй раз не создавать его, а удаляться все созданные объекты
будут только при удалении ComplexObject.
Такой вариант хорош, когда число объектов не растёт неограниченно, а, например, сходится к некоторому пределу (или просто не очень велико). В противном случае накладные расходы будут велики.

Ведь само слово Find подразумевает, что объект может быть не только создан, но и просто найден в списке существующих.

Если же сделать через интерфейсы (вариант тоже неплохой), то возвращённый объект будет сразу же уничтожен, если перестает быть нужным клиенту. Т.е. с большой вероятностью ф-я FindSomething будет именно создавать, а не находить объекты. Если же ты будешь дополнительно хранить на него ссылку где-то в ComplexObject,
то этот вариант не будет отличаться от первого (объект будет уничтожен только при уничтожении ComplexObject).
Но можно, напр., создать внутри ComplexObject при создании объекта список N созданных последними объектов (тоже своего рода кэш), чтобы несколько увеличить срок их жизни (но и чтобы они не хранились бесконечно долго).

В общем, много чего можно придумать.


 
qube ©   (2002-09-20 15:55) [19]


> Старый Паскалист


Спасибо еще раз. Вроде бы как-то привел мозги в порядок.

> В общем, много чего можно придумать.

Это точно! Именно это разнообразие и напрягает :).


 
Digitman ©   (2002-09-20 16:59) [20]

>qube

Технология и методология исп-я интерфейсов в рамках одного и того же приложения , imho, в первую очередь хороша тогда, когда планируется дальнейшее наращивание функциональности приложения за счет реализации новых классов, управляемых уже предопределенными ранее интерфейсными методами/св-вами, но реализующих эти методы/св-ва иным образом

Пример :

- пусть ты определил интерфейс ITransport, предоставляющий некие транспортные методы : Send() и Receive();

- пусть ты определил некий класс TSocketTransport, реализующий транспортные методы интерфейса ITransport посредством Winsock-механизма;

- пусть (чуть позже) ты определил некий новый класс TPipeTransport, реализующий те же самые транспортные методы интерфейса ITransport (уже декларированного ранее и "знакомого" клиенту) посредством NamedPipe-механизма;

- теперь (после декларации и реализации нового класса) ты можешь по запросу клиента создать (в зависимости от сетевой конфигурации и условий) экземпляр того или иного класса и вернуть клиенту ссылку на один и тот же интерфейс ITransport; клиенту ведь без разницы, что делается в результате вызовов им интерфейсных методов ITransport.Send() и ITransport.Receive(), он знает одно : Send() - передатчик, Receive() - приемник; а какой класс в действительности (TSocketTransport или TPipeTransport) это делает и как он это делает - клиенту глубоко наплевать : за это ответствена серверная часть, предоставившая по запросу клиента единый на все случаи жизни интерфейс, за которым скрывается та или иная реальная функциональность.

- завтра ты стал круче в своих познаниях, или условия сетевые позволяют отныне задействование еще одной технологии - и тебе захочется реализовать какой-нибудь еще класс типа TCellphoneTransport; и нет проблем ! клиент даже знать об этом не знает, просто по прежнему запрашивает у сервера для приема/передачи давно известный ему интерфейс ITransport, а сервер с этого момента волен выбирать не из 2-х, а уже из 3-х технологий транспорта.



Страницы: 1 вся ветка

Текущий архив: 2002.10.03;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.021 c
1-8003
CrazyAngel
2002-09-21 15:52
2002.10.03
Как из dll вызвать функцию моей программы ?


14-8154
NeyroSpace
2002-09-06 16:41
2002.10.03
Папа Римский и INTERNET !???


14-8166
Сергей Чурсин
2002-09-05 13:02
2002.10.03
Программирование для мобилок ? -это перспективно ?


7-8189
МИФИст
2002-07-24 21:13
2002.10.03
Красоту навожу...


14-8139
pag77
2002-09-08 01:08
2002.10.03
где скачать delphi_6