Форум: "Основная";
Текущий архив: 2004.01.09;
Скачать: [xml.tar.bz2];
ВнизПравила вызова AddRef Найти похожие ветки
← →
Тимохов (2003-12-16 14:20) [0]type
i = interface
end;
c = object(tinterfacedobject, i)
end;
procedure func1(const a:i)
begin
end;
procedure func2(a:i)
begin
end;
var
a: i;
begin
a := c.create;
func1(a);
func2(a);
end
Вопрос: почему при вызове func1 AddRef не вызывается, а при func2 вызывается? Это именно так - установлено экспериментом. Также про это написано в некоторых книгах.
Вопрос почуму именно так и где в хелпе по Д прочесть, что это должно работать именно так?
← →
Dimka Maslov (2003-12-16 15:08) [1]В первом случае передаётся константа-адрес, а во втором - переменная-копия отсюда и вызов AddRef
← →
Тимохов (2003-12-16 15:12) [2]
> В первом случае передаётся константа-адрес, а во втором
> - переменная-копия отсюда и вызов AddRef
Высказываение до тире очевидно. А высказываение "отсюда и вызов AddRef" ни откуда явно не следует. Разве нет? Где это написано?
← →
Digitman (2003-12-16 15:18) [3]не знаю уж как в Д6, но в Д5.5 утверждение
> func1 AddRef не вызывается, а при func2 вызывается
не верно : AddRef() не вызывается ни в том ни в другом случае, и это вполне объяснимо
единственный же AddRef() вызывается в дан.примере только при вызове
a := c.create;
что опять же вполне объяснимо
← →
Тимохов (2003-12-16 15:19) [4]digitman
Ты успел проверить?
Странно, у меня работает именно так как я описал...
← →
Digitman (2003-12-16 15:23) [5]
> Тимохов © (16.12.03 15:19) [4]
разумеется, проверил
← →
Digitman (2003-12-16 15:25) [6]вот реальный код, который я у себя прогнал, в Д5.5
type
i = interface
end;
c = class(tinterfacedobject, i)
end;
var
o: c;
procedure func1(const a:i);
begin
showmessage(inttostr(o.refcount)); // здесь сч-к = 1
end;
procedure func2(a:i);
begin
showmessage(inttostr(o.refcount)); // и здесь тоже сч-к = 1
end;
procedure TfrmMain.Button4Click(Sender: TObject);
var
a: i;
begin
o := c.create;
a := o;
func1(a);
func2(a);
end;
← →
Тимохов (2003-12-16 15:27) [7]Digitman © (16.12.03 15:23) [5]
Ты не прав. Проверь:
type
IInt = interface
end;
TCl = class(TObject, iint)
FRefCount: Integer;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
end;
function TCl.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
function TCl._AddRef: Integer;
begin
showmessage("addref "+inttostr(frefcount));
Result := InterlockedIncrement(FRefCount);
end;
function TCl._Release: Integer;
begin
showmessage("release "+inttostr(frefcount));
Result := InterlockedDecrement(FRefCount);
if Result = 0 then
Destroy;
end;
procedure func1(const i: iint);
begin
end;
procedure func2(i: iint);
begin
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i: iint;
begin
i := tcl.create();
func1(i);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
i: iint;
begin
i := tcl.create();
func2(i);
end;
← →
VMcL (2003-12-16 15:33) [8]>Digitman © (16.12.03 15:25) [6]
Взял Ваш код, запустил в D6 (6.240 Update Pack 2), вот что вышло:
func1 - 1
func2 - 2
← →
Тимохов (2003-12-16 15:33) [9]Digitman © (16.12.03 15:25) [6]
Проверил твой пример - он говорит о том, что я прав - у меня в первом случае 1, во втором 2. Запустил ровно твой пример без переделок. Правда Д6, но по моим воспоминаниям так и в Д3 было.
← →
VMcL (2003-12-16 15:34) [10]>Тимохов © (16.12.03 15:27) [7]
>Digitman © (16.12.03 15:23) [5]
>Ты не прав. Проверь...
Он же в D5 проверяет :))
← →
Digitman (2003-12-16 15:35) [11]вот реальные результаты вывода сообщений, которые формируются твоим последним кодом [7] в Д5.5:
в ходе обработки 1-й кнопки :
addref 0
release 1
в ходе обработки 2-й кнопки :
addref 0
release 1
← →
Тимохов (2003-12-16 15:36) [12]Все-таки вопрос интересный. В хелпе по дельфе я этого не нашел. Инфа взята из книги Эрика Хармона. Там явно на это акцентировано винимание. Причем не сказано почему именно так.
← →
Тимохов (2003-12-16 15:37) [13]VMcL © (16.12.03 15:34) [10]
Замечу, что такое же поведение у меня наблюдалось в Д3 - за это отвечаю. Я вот тут подумал, может это как-то настройками компилатора регламентируется? Поищу...
← →
Digitman (2003-12-16 15:43) [14]
> Тимохов
скорей всего, это опциональное поведение компилятора
← →
Digitman (2003-12-16 15:45) [15]
> Инфа взята из книги Эрика Хармона
у меня издания от 2000 года (старенькое)
дай ссылку на раздел и/или страницу оригинала, где есть этот акцент - посмотрю что там к чему
← →
Тимохов (2003-12-16 15:46) [16]Digitman © (16.12.03 15:43) [14]
Да, наверное, буду искать.
Вопрос достаточно важен для меня - интерфейсы в программе используются достаточно активно...
← →
Тимохов (2003-12-16 15:50) [17]Digitman © (16.12.03 15:45) [15]
Она у меня дома. Где-то это ближе к началу было при обсуждении общих принципов работы с интерфейсами в Д без применения к ОЛЕ.
Посмотрю - скажу.
← →
Digitman (2003-12-16 16:05) [18]
> Тимохов
все с тобой ясно)
включи оптимизацию компилятора - получишь результат, в точности описанный мной ... и это опять же вполне объяснимо
← →
Digitman (2003-12-16 16:07) [19]к сож. Хармон не упомянул об этом в том фрагменте, на который ты ссылаешься как на заостряющий внимание
если тело ф-ции пусто, компилятору нет никакой необходимости добавлять код модификации сч-ка ссылок, коль от него требуют генерацию оптимального кода
← →
Digitman (2003-12-16 16:10) [20]а по сути вопроса - Хармон прав : компилятор генерирует неявный код управления сч-ком ссылок лишь в том случае, когда интерфейс передается по значению... случаи с декларацией var и const - это случай с передачей по ссылке, а не по значению, поэтому и результат соответствующий
← →
Тимохов (2003-12-16 16:13) [21]Я уже тоже понял, что это от оптимизации зависит. Пытаюсь посмотреть это в asm"е.
Вообще говоря, нехорошо это - кину я помидор в оговод Дельфи.
То, что ты говоришь, что это объяснимо не согласен - оптимизация не должна вилиять на поведение...
На самом деле я проверил, что если в func1 и func2 обращаться к интерфейсу, то будет именно так как я говорю.
В ваше примере кода, действительно, addref вызываться не будет.
← →
Тимохов (2003-12-16 16:14) [22]Digitman © (16.12.03 16:10) [20]
Вот и про тоже - по сути Хармон прав. Где он интересно надыбал такую инфу, кроме как через опыт. Но опыт дело такое - сегодня так, в след. версии по другому. А хочется пользоваться декларированным поведением.
← →
Digitman (2003-12-16 16:15) [23]
> Вообще говоря, нехорошо это
вообще говоря, это оч даже замечательно !
не надо помидоров)
ну ты сам посуди - на кой черт нужно вызывать AddRef() , чтобы тут же вызвать _Release() ?
← →
Тимохов (2003-12-16 16:19) [24]Когда я это писал, я не прорюхал еще фишку, что если в процедурах сделать обращение к интерфейсу, то не зависимо от оптимизации _AddRef будет. Поэтому я думал, что _AddRef не вызывается при оптимизации. Вот это было бы действительно нехорошо. Разве я не прав?
Одним словом вопрос остался - где явно описано обсуждемое поведение?
← →
VMcL (2003-12-16 18:55) [25]>> Тимохов © (16.12.03 16:19) [24]
Не знаю поможет ли, но вот вырезка из Help:
Delphi performs no "unsafe" optimizations that require special awareness by the programmer.
З.Ы.
Думаю, что нигде нет официального описания приемов Delphi"йского оптимизатора, хотя может я и ошибаюсь.
← →
Тимохов (2003-12-16 19:00) [26]VMcL © (16.12.03 18:55) [25]
Спасибо.
Скажу так - про оптимизатор зашла речь только потому, что выяснилось, что он действительно хорошо работает и в некоторых случаях делает, действительно, правильную оптимизацию.
Исходный вопрос был, повторюсь, такой: где в документации по дельфи написано, что при передаче интерфейса в метод, где параметр описан как const НЕ вызывается AddRef, а при передаче в метод, где параметр описан БЕЗ const AddRef вызывается?
← →
VMcL (2003-12-25 16:54) [27]>Тимохов © (16.12.03 19:00) [26]
>>в некоторых случаях делает, действительно, правильную оптимизацию.
LOL!!!
← →
Тимохов (2003-12-25 17:00) [28]Что значит "LOL!!!"?
Наверное это сленг? Просвети.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.01.09;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.34 c