Форум: "Основная";
Текущий архив: 2005.02.13;
Скачать: [xml.tar.bz2];
ВнизСистемная функция IntfCopy Найти похожие ветки
← →
Chlavik © (2005-01-28 17:04) [0]Вот её код...
procedure IntfCopy (var Dest: Pointer; const Source: Pointer);
var
OldDest: Pointer;
begin
OldDest := Dest;
Dest := Source;
if Dest <> nil then IUnknown (Dest).AddRef;
//Release old Dest
if OldDest <> nil then IUnknown (OldDest).Release;
end;
Обьясните пожалуста зачем это всё выполняется Елсли мона там оставить только Dest := Source; AddRef увилечивает и сразу Release уменьшает щётчик одно и тоже cjm обьекта ... ТАк зачем же это делать ?
← →
Александр Иванов © (2005-01-28 17:09) [1]Там увеличивается счетчик сылок на Dest до вызова процедуры и увеличивается для Dest = Source, т.е. которым он станет после выполнения.
← →
Chlavik © (2005-01-28 17:24) [2]Так а где же он там увеличиваеися второй раз ??? если там Release ... А типа тут предусматривают что в Dest что то уже было ...
← →
Александр Иванов © (2005-01-28 17:51) [3]Описался.
Там увеличивается счетчик сылок на Dest до
уменьшается
← →
Набережных С. © (2005-01-28 20:29) [4]>Chlavik ©
Delphi поддерживает автоматическое управление временем жизни интерфейсов, т.е. берет на себя вызов Addrer и Release. Теперь представь, что при вызове Dest уже содержит интерфейс некоего объекта и у этого объекта счетчик ссылок = 1. Если просто присвоить Dest:=Source, то ссылка будет потеряна и объект никогда не будет уничтожен. Следовательно, перед присвоением необходимо вызвать Dest.Release. Но если счетчик Dest был равен 1, то при этом он будет уничтожен. А теперь представь, что и Dest и Source содержат один и тот-же интерфейс. Ну а порядок действий таков, ИМХО, потому, что вероятность исключения при вызове AddRef несопоставимо меньше, чем при вызове Release, который может инициировать уничтожение объекта.
← →
jack128 © (2005-01-28 20:49) [5]Набережных С. © (28.01.05 20:29) [4]
Но если счетчик Dest был равен 1, то при этом он будет уничтожен. А теперь представь, что и Dest и Source содержат один и тот-же интерфейс
Не может быть такого, что и Dest и Source содержат один и тот же интерфейс и при этом его счетчик равен 1.
← →
Набережных С. © (2005-01-28 21:56) [6]>jack128 © (28.01.05 20:49) [5]
Может, и эта процедура ОБЯЗАНА такую возможность учитывать. Разумеется, я подразумевал интерфейсы одного объекта - у интерфейса счетчика не бывает. Просто поставь брекпоинт на эту процедуру, и посмотри, в каких местах она вызывается. Сходу я не готов привести корректный пример, никогда на этом не акцентировался, однако же с таким сталкивался. Да хотя бы вот так:
a: pointer;
b: IInterface;
a:=Pointer(b);
...
b:=IInterface(a);
Грубо, конечно, но суть отражает.
← →
jack128 © (2005-01-28 22:49) [7]Набережных С. © (28.01.05 21:56) [6]
Разумеется, я подразумевал интерфейсы одного объекта
Ну и что?begin
if Assigned(Dest) then
IUnknown(Dest)._Release; // Тут объект никак не может быть не может быть уничтожен, ведь есть еще Source, который ссылается на интерфейс, рализованный этим объектом
Dest := Source;
if Assigned(Dest) then
IUnknown(Dest)._AddRef;
end;
a: pointer;
b: IInterface;
a:=Pointer(b);
...
b:=IInterface(a);
Я только в пятерке работаю, IInterface появился позднее. Для него так же используется автоматический подсчет ссылок?
Если да, то тут проблема в том, что ты пне вызвал addRef после a:=Pointer(b); Вызвал бы - все было б шоколадно, а так AV схлопотал. В моем коде все AddRef/Release вызываются как раз тогда когда нужно, поэтому если подсчет ссылок в объекте реализован верно, но ничего страшного не произойдет..
← →
default © (2005-01-28 23:11) [8]jack128 © (28.01.05 22:49) [7]
правильно Набережных С. толкует
тут тонкая мысль
если же переставить строки
if Dest <> nil then IUnknown (Dest).AddRef;
//Release old Dest
if OldDest <> nil then IUnknown (OldDest).Release;
местами тогда если к примеру у нас одна ссылка на интерфейс получена нормально(учитывая подсчёт ссылок) а другая просто копированием первой то при выполнении кода число ссылок на интерфейс станет равным 2 - справедливость восторжествует иначе этот код всё поломает - прибъёт объект
← →
default © (2005-01-28 23:14) [9]jack128 © (28.01.05 22:49) [7]
правильно Набережных С. толкует
тут тонкая мысль
если же не переставлять строки
if Dest <> nil then IUnknown (Dest).AddRef;
//Release old Dest
if OldDest <> nil then IUnknown (OldDest).Release;
местами тогда если к примеру у нас одна ссылка на интерфейс получена нормально(учитывая подсчёт ссылок) а другая просто копированием первой то при выполнении кода число ссылок на интерфейс станет равным 2 - справедливость восторжествует иначе этот код всё поломает - прибъёт объект
← →
jack128 © (2005-01-28 23:16) [10]default © (28.01.05 23:11) [8]
а другая просто копированием первой
без вызова _AddRef?? Тогда понятно, но нафиг это учитывать? Если кто не хочет следовать правилам работы с интерфейсами, то его личные проблемы...
← →
default © (2005-01-28 23:17) [11]jack128 © (28.01.05 23:16) [10]
я тоже хотел это сказать
казалось бы да - траблы программиста
но дело-то всего-то в порядке строк!никакого дополнительного кода для учёта этой ситуации не писалось, просто нужное расположение
← →
jack128 © (2005-01-28 23:25) [12]default © (28.01.05 23:17) [11]
но дело-то всего-то в порядке строк!
Дело в принципе! Не хочешь следовать правилам - получай по рукам. А то распустились тут.. :-)
← →
default © (2005-01-28 23:26) [13]"Может, и эта процедура ОБЯЗАНА такую возможность учитывать"
вот это, конечно, неверно!
ничего там не обязана она
кого волнует что программист наделал там себе этих ссылок на интерфейс "нелегально"!ей тоже это до лампочки!
← →
default © (2005-01-28 23:27) [14]jack128 © (28.01.05 23:25) [12]
согласен!с другой стороны это даже плохо!прокатит у программиста за счёт этой особенности процедуры(объект не умрёт) - он подумает что всё правильно делает - а так бы понял что нужно внимательно со ссылками на интрфейсы работать
← →
Набережных С. © (2005-01-29 07:30) [15]>jack128 © (28.01.05 23:25) [12]
>IInterface появился позднее. Для него так же используется автоматический подсчет ссылок?
Да
Ты все правильно говоришь об аккуратности, но с точки зрения программиста, просто не учитываешь, что эта проседура как раз и есть часть механизма автоматического подсчета ссылок и с этой точки зрения мой пример и надо рассматривать. Вот смотри:type
IA = interface
["{58B0C86D-799F-4E17-BCD9-5440ABD63020}"]
end;
IB = interface(IA)
["{5736D9AC-AAA5-40A1-8F84-6FDE0D1FA337}"]
procedure Test;
end;
TObj = class(TInterfacedObject, IA, IB)
procedure Test;
end;
{ TObj }
procedure TObj.Test;
begin
//
end;
var
A: IA;
B: IB;
A:=TObj.Create;
A:=A;
Вот здесь и будет этот вариант. Глупо? Конечно. Но программист имеет право так написать, потому, что это не противоречит ни одному правилу языка. А вот Delphi обязано корректно обработать такую конструкцию. Если ты с этим не согласен, то это не ко мне, а к Borland:). Я понимаю, что пример выглядит несколько надуманным, но мне просто лень копаться в исходниках или придумывать что-нибудь реальное. Это давно стало для меня тривиальным и скучным, только не обижайся:) Вот еще одна процедура из той-же области - IntfCast. Она действует чуть иначе, но тот же принцип. Если мы напишем вот так(вполне реально):
A:=A as IB;
то все будет нормально и корректно, а вот если так
A.QueryInterface(IB, A)
то поимеем вполне конкретные неприятности, ибо берем все на себя, а действуем неправильно.
Надеюсь этот пост тебя убедит. Если же нет - извини, ну нет у меня дара убеждать:)
← →
GrayFace © (2005-01-31 19:47) [16]В ветке http://delphimaster.net/view/1-1106922134/ вы сказали:
> представьте что компиллер не включает в код бессмысленные конструкции типа A := A
Не могу представить:) Обязательно включит. Компилятор не может не включать этот код именно в силу автоматического подсчета ссылок. Но об этом лучше в той ветке.
Почему включит?
← →
jack128 © (2005-01-31 22:27) [17]Набережных С. © (29.01.05 7:30) [15]
Надеюсь этот пост тебя убедит. Если же нет - извини, ну нет у меня дара убеждать:)
Как раз таки убедил. Спасибо, вопрос закрыт.
GrayFace © (31.01.05 19:47) [16]
Почему включит?
Именно потому, что вместо A := A; должен сгенериться код с вызовом _AddRef и _Release. Что именно происходит при вызове этих методов компелятор предугадать не в состоянии, так что никак оптимизировать этот код нельзя..
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.02.13;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.052 c