Форум: "Основная";
Текущий архив: 2003.10.30;
Скачать: [xml.tar.bz2];
ВнизИнтерфейсы и result Найти похожие ветки
← →
Стекляшкин (2003-10-17 10:12) [0]Здравствуйте.
Есть интерфейс
type
iMyInterface = interface
end;
TMyImlp = class (TinterfacedObject)
end;
function CreateObject() : iMyInterface;
begin
result := TmyImlp.Create;
// Кол-во блокировок 1
end;
Далее где-то в программе:
var
itf : iMyInterface;
begin
itf := CreateObject();
// Кол-во блокировок равно 2
itf.Что-то
itf := nil; // Объект не удаляется!!!!!! Так как число блокировок равно 1
end;
В итоге мы имеем, что интерфейс переданный через result всегда имеет количество блокировок равное 1, это значит объект этого интерфейса никогда не удалится, в отличие от использования CreateObject( out intf : Imyinterface ), который блокировку не добавляет.
Это есть баг Delphi или что???
← →
Стекляшкин (2003-10-17 10:13) [1]Мда, пардон ,класс наследуется так же и от интерфейса
TMyImpl = class(TInterfacedObject,iMyInterface);
← →
Плохиш_ (2003-10-17 10:32) [2]>Стекляшкин (17.10.03 10:12)
> Это есть баг Delphi или что???
Это есть баг господина Стекляшкин, который почему-то не знает основ ООП и работы с объектами.
Рекомендую подумать над тем, что происходит в системе при TmyImlp.Create
← →
Стекляшкин (2003-10-17 11:04) [3]Ой, родной, не учите меня жить, я прекрасно понимаю и основы и не только основы.
При Create ничего не происходит кроме создания объекта!!!!
Посмотри исходники system.pas конструктор у TInterfacedObject
если ты там найдешь увеличение ссылки на интерфейс я тебе пиво поставлю или если ты там вообще найдешь конструктор.
Создается объект и как только он присваивается интерфейсу у него автоматом происходит AddRef. Если я создам объект и не присвою его интерфейсу кол-во ссылок на него будет равно 0
with TMyImlp.Create do
begin
// Что-то
// НЕТ ССЫЛОК ДО ТЕХ ПОР, ПОКА Я НЕ ПРИСВОЮ ЕГО ИНТЕРФЕЙСУ
Free;
end;
var
my : TMyImlp;
my := TMyImpl.Create; // НЕТ ССЫЛОК, НО ЕСТЬ УКАЗАТЕЛЬ
intf := my as Imyinterface; // ЕСТЬ ССЫЛКА!!!!! +1
// ТЕПЕРЬ МОГУ УКАЗАТЕЛЬ ХОТЬ В NIL СВЕСТИ все равно все будет работать
Теперь по существу. result идет как var параметр в процедуре.
Но ссылка у него не должна увеличиваться!!!!
Ссылка должна увеличиваться только тогда когда я результат присваиваю переменной. Именно это есть баг из-за тупого вызова самим Delphi AddRefa
← →
Плохиш_ (2003-10-17 11:09) [4]>Стекляшкин (17.10.03 11:04) [3]
> Теперь по существу. result идет как var параметр в процедуре.
> Но ссылка у него не должна увеличиваться!!!!
Т.е. result - это не переменная?
← →
Стекляшкин (2003-10-17 11:11) [5]Блин, да переменная это, переменная, но для интерфейсов должна идти как out, а не как var переменная!!!!!
Что-то типа CreateObject( out int : IMyInterface ); только как возврат в функцию!
вот это и есть баг!
← →
Плохиш_ (2003-10-17 11:18) [6]>Стекляшкин (17.10.03 11:11) [5]
Кому ...должна... ?
← →
Стекляшкин (2003-10-17 11:23) [7]Ответь по существу! Отвечаете только на вопросы типа как мне DLL загрузить. Ламота. Если не знаешь так и скажи не знаю.
← →
Плохиш_ (2003-10-17 11:25) [8]>Стекляшкин (17.10.03 11:23) [7]
Не вижу вопроса без ответа.
← →
Стекляшкин (2003-10-17 13:54) [9]> Не вижу вопроса без ответа.
Ослеп что ли?
← →
Ломброзо (2003-10-17 14:11) [10]> Стекляшкин (17.10.03 13:54) [9]
Мне кащется, вы - буйный!
← →
Goffman (2003-10-17 14:21) [11]2Стекляшкин
Из книги Эрика Хармона: "Квалификатор параметра var или const заставляет Delphi передавать передавать интерфейс по ссылке, а не по значению. Передача же по значению и приводит к вызовам _AddRef и _Release".
Так что то, что вы называете багом, на самом деле запрограммированный мехагизм:)
← →
Кулюкин Олег (2003-10-17 14:30) [12]
> Ой, родной, не учите меня жить, я прекрасно понимаю и основы
> и не только основы.
Мощно задвинул, внушает! (с) Гоблин
← →
Vuk (2003-10-17 14:30) [13]to Стекляшкин:
Проверил. Глюк не подтвердился, все замечательно уничтожается. Сдается мне, что-то Вы от общественности скрываете...
Тестовое приложение:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
IMyIntf = interface
["{B1D5C839-877C-4B27-9615-D1EE2CE06D24}"]
procedure Test;
end;
TMyObject = class(TInterfacedObject, IMyIntf)
public
procedure Test;
public
destructor Destroy; override;
end;
{ TMyObject }
destructor TMyObject.Destroy;
begin
writeln("destroyed");
inherited;
end;
procedure TMyObject.Test;
begin
writeln("Test");
end;
function CreateObj: IMyIntf;
begin
Result := TMyObject.Create;
end;
procedure TestProc;
var
i: IMyIntf;
begin
i := CreateObj;
i.Test;
i := nil; //<- наличие этой строки ни на что не влияет
end;
begin
TestProc;
readln;
end.
← →
Стекляшкин (2003-10-17 14:40) [14]Получается, что result возращает интерфейс по значению, что в корне неверно! Именно это и является недоработкой самого языка Object Pascal.
Теперь привожу Вам,любезнейшие, выдержечку из Object Pascal Language Guide:
... the result is returned in an additional var parameter that is passed to the function after the declared parameters
Все понятно? Так какого ж тогда ссылка то увеличивается.
Короче если я присваиваю resultу интерфейс, ни при каких обстоятельстах при этой операции ссылка не должна увеличиваться!!!
← →
Стекляшкин (2003-10-17 14:43) [15]Что уничтожается??? У тебя переменная интерфейса в локальной области видимости, поэтому и не влияет. Он делает ей еще один ReleaseRef при выходе из TestProc!
← →
Vuk (2003-10-17 14:50) [16]to Стекляшкин:
>У тебя переменная интерфейса в локальной области видимости,
>поэтому и не влияет.
А у Вас в какой области видимсоти переменная?
var
itf : iMyInterface; //<- вот это какая по-Вашему область видимости?
begin
...
end;
← →
Стекляшкин (2003-10-17 14:56) [17]Вы представляете себе программу, которая использует БОООЛЬШООЙ COM сервер, который состоит из огромного числа объектов, причем каждый объект может порождать другие объекты у себя внутри и выдворять их наружу. Сервер этот используется, допустим, 10-ю клиентами. Так сколько там областей видимости??? Где они? И какие? Область видимости это по определению блок, в котором существуют переменные. В моей задаче у интерфейсов область видимости есть все приложение.
← →
Vuk (2003-10-17 15:21) [18]Ну так и нечего на компилятор тогда валить. :o)
← →
Стекляшкин (2003-10-17 15:35) [19]Нет, меня здесь решительно не поймут
← →
Vuk (2003-10-17 15:43) [20]Действительно, если Вы хотите свалить проблемы на компилятор, когда он решительно ни в чем не виноват, то Вас здесь не поймут. А что компилятор не виноват я показал на примере. И если не затруднит, проясните, что за новая область видимости - "все приложение". Кстати, с интерфейсными переменными возможен один баг (см. http://www.delphikingdom.com/stones/stone_42.htm и почитайте там обсуждение).
← →
Digitman (2003-10-17 15:52) [21]
> Стекляшкин
результат интерфейсного типа есть по сути результат указательного типа
результаты указательных типов по умолчанию возвращаются по значению, в виде содержимого регистра eax
это - к вопросу о возврате рез-та подобных типов якобы по ссылке
к вопросу об "области видимости"
чувствуется непонимание с твоей стороны совершенно разных терминов и механизмов : "область видимости" и "время жизни" переменной
последний механизм имеет прямое отношение к тому, что ты наблюдаешь со сч-ком ссылок
← →
Goffman (2003-10-17 15:59) [22]
> Получается, что result возращает интерфейс по значению,
> что в корне неверно!
> Все понятно? Так какого ж тогда ссылка то увеличивается.
>
Нет, как раз получается, что возвращается по ссылке, так как ссылка в теле самой процедуры не увеличивается(Можешь проверить код который предоставил Vuk ©).
Из процедуры выходит объект с нулевым счетчиком, и увеличение счетчика происходит только при присваивании
ps: в первом посте я немного напутал, прошу извинить
← →
Стекляшкин (2003-10-17 16:28) [23]Да вы хоть сами определитесь- один говорит по ссылке, другой по значению. Все равно неверно не то и не то.
Если по ссылке - тогда не должна увеличиваться. Если по значению, то это неправильно передавать интерфейс по значению, так как я могу и не захотеть увеличивать ссылку.
Теперь про время жизни:
Область видимости result - функция в которой она существует. Время жизни - тоже пока функция работает. Так вот компилятор должен при выходе из процедуры убрать за собой все ссылки на объекты, или не создавать их вообще! Где тут нелогичность? Почему я должен попадать в неоднозначные ситуации из-за того, что дельфи берет на себя работу по AddRef и ReleaseRef.
← →
Digitman (2003-10-17 16:39) [24]
> Стекляшкин
> Так вот компилятор должен при выходе из процедуры убрать
> за собой все ссылки на объекты
он и уберет).. если ты не присвоишь рез-т вызова ф-ции ни одной переменной ... т.е. вызовешь ф-цию как процедуру
а если полученная ссылка на интерфейс была таки зафиксирована в переменной интерфейсного типа, то для каждой такой переменной (вне зависимости от времени ее жизни) компилятор генерирует код с проверкой переменной на не-NIL и последующий неявный вызов _Release, если не-NIL = True... код этот будет неявно исполняться перед тем как переменной пришло время "умереть"
← →
Стекляшкин (2003-10-17 16:55) [25]Все-таки это баг. Сходил по ссылке, посмотрел.
Только вот где гарантия, что клиент моего объекта будет работать по правилам. Спасибо Digitman и Vuk за ссылку и конструктивные замечания.
← →
Digitman (2003-10-17 17:10) [26]
> Стекляшкин
> Все-таки это баг
слабо верится.
привел бы реальный код
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.10.30;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.011 c