Теряются объекты передаваемые в качестве параметров интерфейсных типов в случае, когда не происходит кастинга с проверкой (as) к определенному интерфейсу. Для кода:
Test(TMyObject.Create('1')); // will not be destroyed
Test(IInterface(TMyObject.Create('2'))); // will not be destroyed
Test(TMyObject.Create('3') As IInterface);
утечки будут в первых двух вызовах. Воспроизводится, и на Turbo Delphi, и на Delphi 2009. Отчет #71015.
10 комментариев:
Не могу повторить, а в поле Attachment на QC обычный текст. Не могли бы вы выолжить полный текст примера прямо тут? Он не должен быть большим.
Проверил QC, там все нормально (проверял через стандартного QC-клиента).
Код:
program intfs;
{$APPTYPE CONSOLE}
Type
TMyObject = Class(TInterfacedObject)
FName : String;
Constructor Create(Const AName : String);
Destructor Destroy; Override;
End;
{ TMyObject }
constructor TMyObject.Create(const AName: String);
begin
Inherited Create;
FName := AName;
end;
destructor TMyObject.Destroy;
begin
inherited;
Writeln('Object ', FName, ' is destroyed');
end;
//
Procedure Test(Const AIntf : IInterface);
Begin
End;
//
begin
Test(TMyObject.Create('1')); // will not be destroyed
Test(IInterface(TMyObject.Create('2'))); // will not be destroyed
Test(TMyObject.Create('3') As IInterface);
//
// Output:
//
// Object 3 is destroyed;
//
end.
По-моему это as designed.
Если мы передаем в процедуру объект, то с какого перепуга этот объект должен самостоятельно уничтожиться?
Предположим, что "баг" исправлен. Что тогда будет с кодом:
First := TMyObject.Create('4');
Second := First;
Test(First);
при условии, что Second - глобальная переменная (TMyObject), которую мы будем использовать уже после выхода First за пределы видимости? Скорее всего будет AV.
P.S. Работать надо или с объектами или с интерфейсами. Мешать не стоит.
>Если мы передаем в процедуру
>объект, то с какого перепуга этот
>объект должен самостоятельно
>уничтожиться?
С какого перепугу мы передаем объект? В параметре, что объектный тип используется?
Конструктор возвращает объект. В метод с параметром типа byte можно передать переменную типа integer, но снаружи вызываемого метода она останется integer.
Если не хочется "странного" поведения, то при создании объекта нужно присваивать его интерфейсной переменной и работать через нее, а про тип объекта забыть.
P.S. На QC заходил через браузер (Опера, IE7).
>Конструктор возвращает объект.
>В метод с параметром типа byte
>можно передать переменную типа
>integer, но снаружи вызываемого
>метода она останется integer.
Не нужно передергивать. Byte, Integеr и иже с ними не являются типами с управляемым временем жизни, в отличие от интерфейсных типов.
>Если не хочется "странного"
>поведения, то при создании
>объекта нужно присваивать его
>интерфейсной переменной и
>работать через нее, а про тип
>объекта забыть.
Мне не требуется ни каких переменных. Я вполне осознанно отдаю объект, зная, что он будет приведен к интерфейсному типу и потому о времени его жизни не беспокоюсь. А то, что наблюдается есть чистейший баг.
P.S. На QC заходил через браузер (Опера, IE7).
Глюки QC. Через клиент все работает нормально.
>Не нужно передергивать. Byte, >Integеr и иже с ними не являются >типами с управляемым временем >жизни, в отличие от интерфейсных >типов.
Ну хорошо, скажу по другому:
В процедуру с параметром типа string (управляемый тип, в вашем случае интерфейс) можно передать переменную типа char или, например, string[10] (неуправляемые типы, в вашем случае объект).
Тут конечно ситуация слегка разнится, потому, что строка в памяти будет скопирована, но внешнее поведение аналогично - после передачи char'а в процедуру я могу с ним спокойно работать и не опасаться что его память освобождена.
Вы же предлагаете, чтобы после передачи объекта в процедуру, требующую интерфейс, этот объект помирал (поскольку интерфейсных ссылок на него больше нет), и воспользоваться им после этого нельзя было.
>В процедуру с параметром типа
>string (управляемый тип, в вашем
>случае интерфейс) можно передать
>переменную типа char или,
>например, string[10]
Еще раз: не нужно передергивать. Любые аналогии здесь не уместны.
>Вы же предлагаете, чтобы после
>передачи объекта в процедуру,
>требующую интерфейс, этот объект
>помирал (поскольку интерфейсных
>ссылок на него больше нет), и
>воспользоваться им после этого >нельзя было.
Это не я предлагаю, это правило языка.
Причина - в спецификаторе const формального параметра -
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=609
Неприятная особенность
Отправить комментарий