Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.02.27;
Скачать: [xml.tar.bz2];

Вниз

Посягательство на святое… То бишь (шепотом) - компилятор   Найти похожие ветки 

 
Ihor Osov'yak ©   (2005-02-09 16:10) [0]

Или (может) ошибка в коде, генерируемом компилятором.

В общем-то такой безобидный код:

function iDocToString(const iDoc: IHTMLDocument2): string;
var
 S: TStringStream;
begin
 result := "";

 if not assigned(iDoc) then
   exit;
 S := TStringStream.Create("");
 try
   (iDoc as IPersistStreamInit).Save(TStreamAdapter.Create(S), True);
   Result := S.DataString;
 finally
   S.Free;
 end;
end;


При танцах вокруг него  было обнаружено, что деструктор TStreamAdapter не вызывается. На всякий случай - декларация IPersistStreamInit.Save:

   function Save(const stm: IStream; fClearDirty: BOOL): HResult; stdcall;

то есть результат работы конструктора должен преобразовываться к интерфейсной ссылке, под которую компилятор неявно создает локальную переменную, и во время выхода которой из области видимости буде вызван _Release, которым в данном случае есть  function TInterfacedObject._Release, так как TStreamAdapter наследуется от TInterfacedObject, ну и собственно из _Release  должен быть вызван деструктор, так как счетчик ссылок будет сброшен в 0 (установка в 1 должна происходить в момент получения от созданного экземпляра TStreamAdapter интерфейса IStream перед передачей последнего как параметр для IPersistStreamInit.Save....

Но увы. деструктор не вызывался.
Мало того, при трассировании кода по CtrlAltC было установлено, что не вызывался не только _Release, а и _AddRef - то есть похоже компилятор забывает это делать для локальной интерфейсной ссылки, которую он сам и создает... Во всяком случае в этом примере кода. Провералось только в D7.

Да, если явно описать локальную интерфейсную ссылку:

function iDocToString(const iDoc: IHTMLDocument2): string;
var
 S: TStringStream;
 iStm: IStream;
begin
 result := "";

 if not assigned(iDoc) then
   exit;
 S := TStringStream.Create("");
 try
   iStm := TStreamAdapter.Create(S);
   (iDoc as IPersistStreamInit).Save(iStm, True);
   Result := S.DataString;
 finally
   S.Free;
 end;
end;


- то деструктор вызывается - но вопросы все же остаются - _AddRef вызывается только в момент присваивания iStm,  а _Release - в момент ухода из области видимости. Но вот в момент вызова  IPersistStreamInit.Save методы подсчета ссылок не дергается - и хотя во второй реализации функции это не критично, но все же.. бардак однако..


 
Ihor Osov'yak ©   (2005-02-09 16:17) [1]

Собственно было бы интересно послушать мнение уважаемого сообщества относительно обрисованной выше фишки...
Имеет факт некоректности место быть, или присутсвует некоторое непонимание с моей стороны?


 
У   (2005-02-09 17:38) [2]

Это известная фича, обсуждалась, кажется, в Королевстве.

Т.е. результат работы конструктора к интерфейсному типу преобразуется,
а вот неявную локальную переменную компилятор не создаёт.
Да, наверное, и не должен.


 
Ihor Osov'yak ©   (2005-02-09 18:17) [3]

> Т.е. результат работы конструктора к интерфейсному типу преобразуется,

Это и понятно.

> а вот неявную локальную переменную компилятор не создаёт.
это его проблемы, но см. ниже.

Но он обязан вызвать _AddRef - так как начинает работать с обьектом по интерфейсной ссылке (передает как параметр в процедуру, то есть перед передачей параметра). С последующем вызовом _release, когда потеряет интерес к обьекту (после возврата из процедуры). Но вот вызвать _release без создания локальной переменной или чего то в этом роде он не сможет.

Посему с
> Да, наверное, и не должен.
несогласен.

То есть я все же пока настроен считать, что соотв. фича есть недоработка Борланда..

Зы. ввиду сущесвования паралельной ветки, которую я создал то ли из-за неумения пользоваться форумом, то ли из-за того что вовремя не увидел этой ветки из-за сбоев на сервере - предложения продолжать дисскусию там - http://delphimaster.net/view/15-1107956805/


 
icWasya ©   (2005-02-09 20:39) [4]

Вы писали
  function Save(const stm: IStream; ....

так вот этот const и говорит, что _addref/_release не будут вызываться


 
Ihor Osov'yak ©   (2005-02-10 00:48) [5]

2 [4] icWasya ©   (09.02.05 20:39)

> так вот этот const и говорит, что _addref/_release не будут вызываться

Почему? Где это написано?
Да и нелогично - во время работы процедуры, которой передано интерфейсная ссылка нужно гарантировать, что соотв. ком обьект не будет уничтожен. А это без вызова _addref нельзя сделать.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2005.02.27;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.034 c
14-1107762526
UY
2005-02-07 10:48
2005.02.27
Shareware


1-1107798214
Алексей Петухов
2005-02-07 20:43
2005.02.27
Clipboard


1-1108114178
Нулевой
2005-02-11 12:29
2005.02.27
Как закрыть форму поиска по базе данных?


4-1105603248
__max__
2005-01-13 11:00
2005.02.27
Как мне отследить изменение числа процессов в системе?


8-1100373842
RedLord
2004-11-13 22:24
2005.02.27
почему так работает TIMAGE





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