Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.10.30;
Скачать: CL | DM;

Вниз

Интерфейсы и 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;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.027 c
1-98724
Wiz@rd
2003-10-20 22:54
2003.10.30
WMI


7-98900
Е-Моё имя
2003-08-17 18:41
2003.10.30
GetProcAddress и kernel32.dll


1-98711
Alesha aka Pokemon
2003-10-21 09:30
2003.10.30
Компонент TurboPower Product Suite


3-98486
saNat
2003-10-09 01:33
2003.10.30
Динамическое создание компонента DBLookUpComboBox


4-98927
wicked
2003-08-25 20:44
2003.10.30
о таймерах....