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

Вниз

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

 
Ihor Osov'yak ©   (2005-02-09 16:46) [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:50) [1]

Ой, похоже я не разобрался между междуфорумными перебросками..


 
Гаврила ©   (2005-02-09 17:12) [2]


> бардак однако..


не бардак, а фича


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

а почему фича? Бардак он и Африке бардак.


 
Гаврила ©   (2005-02-09 17:37) [4]

В африке бабуины программируют

http://www.newsru.com/world/06Aug2003/baboo.html

обленились ,панимаешь... все за них считают ,и адрефы ,и релизы ,а они еще и недовольны :-)))

а если серьезно
откуда компилятору знать, что ты туда подставил?
Нет у тебя интерфейсной ссылки на IStream в первом случае, просто нет


 
Набережных С. ©   (2005-02-09 17:44) [5]

>Ihor Osov"yak ©   (09.02.05 16:50) [1]

ИМХО, тут дело в спецификаторе const. Возникает некоторая неоднозначность, которую компилятор не может разрулить. Честно говоря, подробностей уже не помню, потому как разбирался с этим года три назад, а потом просто взял за правило. Я столкнулся с этим, когда после вызова некоторых методов импортированных интерфейсов объект "вдруг" уничтожался, хотя ссылки на него еще были. Дело оказалось в том, что некоторые интерфейсные параметры в ActiveX были объявлены без const. Когда исправил объявления, все заработало. Там, кстати, и некоторые параметры типа TGUID объявлены без const. Руки бы пообрывал:). И, по-моему, в каких-то других модулях я на такое-же нарывался. С тех пор взял за правило проверять объявление интерфейсов и редкоизпользуемых функций WinAPI, прежде чем к ним обращаться.
Если моя мысль верна, то проблема должна ичезнуть, если вызывать метод так:
(iDoc as IPersistStreamInit).Save(TStreamAdapter.Create(S) as IStream, True);


 
Ihor Osov'yak ©   (2005-02-09 18:21) [6]

2 Гаврила ©   (09.02.05 17:37) [4]
> Нет у тебя интерфейсной ссылки на IStream в первом случае, просто нет

Вот с этого места и поподробнее.

2 Набережных С. ©   (09.02.05 17:44) [5]

Спасибо, сейчас проверю. Оно выглядит более красиво и естественно, чем явное введение локальной переменной.

зы. Из за сбоев на сервере (или своей несообразительности) я создал дублирующую ветку - см. http://delphimaster.net/view/1-1107954615/

предлагаю дискуссию продолжать здесь - а стоящий внимания постинг с той ветки я цитирую сюда:
============
У   (09.02.05 17:38) [2]
Это известная фича, обсуждалась, кажется, в Королевстве.

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

--------------------------------------------------------------------------------
Ihor Osov"yak ©   (09.02.05 18:17) [3]
> Т.е. результат работы конструктора к интерфейсному типу преобразуется,

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

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

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

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

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

===========



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

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

Наверх




Память: 0.5 MB
Время: 0.041 c
14-1107948735
esu
2005-02-09 14:32
2005.02.27
Вот такая задачка по программированию, есть ли решение ?


1-1107863839
Chip
2005-02-08 14:57
2005.02.27
Не пересекаются ли созданные Panel??????


4-1105952573
tradakad
2005-01-17 12:02
2005.02.27
рисование на окне иконки


14-1107344630
saNat
2005-02-02 14:43
2005.02.27
Ищу материал


14-1107759179
KSergey
2005-02-07 09:52
2005.02.27
Книжки по С++





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