Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
14-98793
Gfa
2003-10-04 19:37
2003.10.30
MyIE


1-98539
stone
2003-10-20 16:33
2003.10.30
Column.AutoSize в TListView


1-98740
vvvvvvv
2003-10-20 14:40
2003.10.30
Как у StringGrid сделать Flat SсrollBar?


4-98935
выарп
2003-08-24 17:52
2003.10.30
Кто знает формат .bmp, помогите


3-98453
nick-from
2003-10-11 12:13
2003.10.30
значение NULL в ХП





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