Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-7915
Fog
2002-09-19 15:32
2002.10.03
Чужие переменные...


7-8188
REL_
2002-07-26 10:12
2002.10.03
Серийный номер винчестера


4-8217
ToLIk2003
2002-08-16 18:10
2002.10.03
список процессов


4-8236
p@s
2002-08-16 12:06
2002.10.03
Запретить выход из другого приложения


3-7829
Alex-kosmonavt
2002-09-12 15:24
2002.10.03
TQuery добавление записи с использованием SQL





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский