Форум: "Основная";
Текущий архив: 2002.10.03;
Скачать: [xml.tar.bz2];
Вниз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;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.007 c