Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.53 MB
Время: 0.033 c
10-1083227214
Господин Уэф!
2004-04-29 12:26
2005.02.13
Как выставить окно Excel "всегда наверху"?


8-1098894068
Sonic_gd
2004-10-27 20:21
2005.02.13
Неработает mediaPlayer


3-1105529961
grigory
2005-01-12 14:39
2005.02.13
Публикация базы в интернете!


1-1107077596
focor
2005-01-30 12:33
2005.02.13
Вскрыть кнопку


4-1104059945
pomashok
2004-12-26 14:19
2005.02.13
управление громкостью





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский