Форум: "Основная";
Текущий архив: 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.043 c