Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Подводные камни
  
О разделе

Список по категориям
Общий список

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  18:01[Войти] | [Зарегистрироваться]

Обсуждение материала
КОМПИЛЯТОР.Не производится финализация интерфейсных ссылок в основном модуле
Полный текст материала


Другие публикации автора: Алексей Вуколов

Цитата или краткий комментарий:

«... Согласно концепции интерфейсных ссылок, они должны обнуляться при выходе из области видимости. И это правило работает нормально, если такие ссылки объявлены как поля в классах или как переменные в процедурах и модулях. ...»


Важно:
  • Страница предназначена для обсуждения материала, его содержания, полезности, соответствия действительности и так далее. Смысл не в разборке, а в приближении к истине :о) и пользе для всех.
  • Любые другие сообщения или вопросы, а так же личные эмоции в адрес авторов и полемика, не относящаяся к теме обсуждаемого материала, будут удаляться без предупреждения авторов, дабы не мешать жителям нормально общаться.
  • Размер одного сообщений не должен превышать 5К. Если Вам нужно сказать больше, сделайте это за два раза. Или, что в данной ситуации правильнее, напишите свою статью.
Всегда легче осудить сделанное, нежели сделать самому. Поэтому, пожалуйста, соблюдайте правила Королевства и уважайте друг друга.



Добавить свое мнение.




Смотрите также материалы по темам:
[Интерфейсы COM-объектов] [Классы] [Жизненный цикл]

Комментарии жителей
Отслеживать это обсуждение

Всего сообщений: 23

20-11-2006 17:11
Вообще-то, всегда думал, что это нормальное поведение компилятора и никогда не закладывался на автоматическую финализацию глобальных переменных.
Нет не нормальное, не надо забывать о том что есть такая штука как пакеты (ну и DLL тоже) и их загрузка/выгрузка не должна приводить к ошибкам и утечкам.
К тому же компилятор всё это учитывает, посмотрите на код который он вставляет в finalize (ставьте метку на "end."), там финализируется всё, и интерфейсы, и строки, и массивы, и локальные типизированные константы, а то что описано в статье это просто глупый баг, забыли что-то где-то добавить для интерфейсов и всё.
 DRON


20-11-2006 03:14
Вообще-то, всегда думал, что это нормальное поведение компилятора и никогда не закладывался на автоматическую финализацию глобальных переменных.


03-11-2006 10:15
сообщение от автора материала
>>>это не баг а нормальная ситуация, переменная не вышла за область своей видимости,undefined

Время жизни такой переменной равно ремени жизни пограммы и переменная выходит за область видимости, когда программа завершается. Так что все-аки баг.

Что же касается строк и других ресурсов, то строки находятся в куче и умрут вместе с ней, поэтому их можно и не финализировать. А вот с интерфейсами сиуация особая.


02-11-2006 02:14
ДА чего вы спорите это не баг а нормальная ситуация, переменная не вышла за область своей видимости, ведь вы ее инициализируете в коде инициализации, а кода финализации нет, вот компилятору и некуда вставлять свой код. Касается, что главного модуля проекта, что секции initialization остальных модулей :)


12-10-2006 00:50
хочу дополнить что это относиться не тока к интерфейсам, но и к строкам и другим ресурсам, с автоматическим уничтожениям...


02-02-2004 14:21
>ОДНАКО, если в примере к "камню" вызвать в теле
>программы метод i._release, то деструктор
>вызываеться.
Понятное дело, вызывается. Но дело в том, что по всем правилам вызов _Release не нужен. Мало того, это может повлиять на правильность подсчета ссылок.


02-02-2004 06:07
ОДНАКО, если в примере к "камню" вызвать в теле программы метод i._release, то деструктор вызываеться.


20-03-2003 11:44
сообщение от автора материала
>Так что привычку не заводить глобальные переменные без инициализации
>надо распространить не только на модули, но и на весь проект.
Так именно про это я и писал! :o)


20-03-2003 11:21
to Алексей Вуколов
Когда я запустил такой код:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Unit1 in "Unit1.pas";

type
    TSomeObject = class(TInterfacedObject)
      constructor Create;
      destructor Destroy; override;
    end;

{ TSomeObject }

constructor TSomeObject.Create;
begin
  writeln("Created");
end;

destructor TSomeObject.Destroy;
begin
  writeln("Destroyed");  
  inherited;
end;

var
  i : IUnknown = nil;
begin
  i := TSomeObject.Create;
end.

то объект i уничтожился. Так что привычку не заводить глобальные переменные без инициализации надо распространить не только на модули,
но и на весь проект.


18-03-2003 22:44
сообщение от автора материала
to Sunny:
Кстати да, действительно. Я не обратил на это внимания сразу только потому, что не имею привычки заводить глобальные переменные без инициализации. Кстати, начальная инициализация переменных заставляет компилятор вставлять код финализации. =8-|

То есть, если написать
var
i : integer = nil;

то все будет работать так, как должно.

Так вот и родился ещё один путь обхода проблемы. :o)

P.S. На днях запостил описание бага в Quality Central. Бум посмотреть чем это кончится...



17-03-2003 14:57
У меня такая-же ситуация получилась и в модуле:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Unit1 in "Unit1.pas";
begin
end.

//////////////// Unit1 //////////////////

unit Unit1;

interface

implementation

type
    TSomeObject = class(TInterfacedObject)
      constructor Create;
      destructor Destroy; override;
    end;

{ TSomeObject }

constructor TSomeObject.Create;
begin
  writeln("Created");
end;

destructor TSomeObject.Destroy;
begin
  writeln("Destroyed");  
  inherited;
end;

procedure T1;
var
   i : IUnknown;
begin
  i := TSomeObject.Create;
end;

var
   i : IUnknown;
initialization
  i := TSomeObject.Create;
  T1;
end.

Уничтожился только объект в процедуре T1.


13-03-2003 19:40
сообщение от автора материала
>>>Где он это делает?
Help читайте. Там написано в каких случаях что происходит. В основном счетчики ссылок щелкают при передаче параметров, присвоении и выходе из области видимости. Все достаточно просто.


13-03-2003 19:10
Да? А если я вызываю сторонний COM сервис. Он сам считает ссылки на себя, но и компилятор Delphi считает свои. Где он это делает? Я бы хотел видеть момент вызова _Release и _AddRef. А циклические ссылки?


13-03-2003 14:24
сообщение от автора материала
to MAD:
>>>Но там я могу посмотреть код, который считает ссылки.
В Delphi тоже. См. методы _AddRef и _Release в TInterfacedObject.


13-03-2003 14:11
сообщение от автора материала
to MAD:
>>>Но там я могу посмотреть код, который считает ссылки.
В Delphi тоже. См. методы _AddRef и _Release в TInterfacedObject.


13-03-2003 14:04
А String ... не скажу что char* лучше, тут вы правы :-)))


13-03-2003 14:02
To: Алексей Вуколов

Про смарт указатели я знаю. Но там я могу посмотреть код, который считает ссылки. В Delphi же я не могу этого увидеть - это вшито в компилятор. Вот это лажа. Язык и библиотека реализаций должны как мне кажется чётко разделены.


13-03-2003 11:38
сообщение от автора материала
to Karbazol:
>>>Объект в такой ситуации не создается, а значит и разрушать нечего ;-)

Извините, но это чушь. Вы код-то получившийся смотрели или как?

to MAD:
>>>Я пересел с С++ на паскаль. И концепция закадрового подсчета ссылок меня несколько напрягает.

Ну если с C++, то про автоматическое разрушение экземпляров классов по выходу из области видимости а также про smart-указатели для COM объектов Вы знать должны. Здесь та же самая по смыслу техника используется.

Кстати, концепция подсчета ссылок для string не напрягает?


>>>А так как есть - лажа.

Лажа получается только в одном месте. В каком - я ясно показал. В остальных случаях это все прекрасно работает. Я интерфейсами достаточно активно пользуюсь во многих проектах.


13-03-2003 09:45
Цитату привести не могу. Но такой совет я когда то запомнил. Вообще я всегда использовал функциональное замыкание - для объекта
var
SomeObject:TSomeObject;
begin
SomeObject:=nil;
try
  SomeObject:=TSomeObject.Create;
  //тут чего-то делаем
  SomeObject.SomeMethod;
finally
  FreeAndNil(SomeObject);
end;
end;

по аналогии для интерфейса
var
SomeRef:ISameIntf;
begin
SomeRef:=nil;
try
  SomeRef:= TSomeObject.Create;
  SomeRef.SomeMethod;
finally
  SomeRef := nil;
end;
end;

Я пересел с С++ на паскаль. И концепция закадрового подсчета ссылок меня несколько напрягает. Если бы это было опциональным - это одно. Была бы полезная фича, уменьшающая кол-во ошибок и дающая нужную гибкость. А так как есть - лажа.



13-03-2003 03:34
//А как вам такой вариант?
//Объект в такой ситуации не создается, а значит и разрушать нечего ;-)
//Это не камень, а оптимизация

program Stone;
{$APPTYPE CONSOLE}
uses
  SysUtils;
type
    TSomeObject = class(TInterfacedObject)
      constructor Create;
      destructor Destroy; override;
    end;

{ TSomeObject }

constructor TSomeObject.Create;
begin
  writeln("Created"); //<- сюда управление не попадает
end;

destructor TSomeObject.Destroy;
begin
  writeln("destroyed");  //<- сюда управление не попадает
  inherited;
end;

var
   i : IUnknown;
begin
  i := TSomeObject.Create;
end.


12-03-2003 18:53
сообщение от автора материала
to MAD:
>Как кстати и положено делать прилежным мальчикам
Пожалуйста приведите цитату из документации, где написано, что так делать необходимо. В свою очередь, цитату, в которой говорится, что интерфейсные ссылки финализируются при выходе из области видимости привожу:

Interface references are managed through reference-counting, which depends on the _AddRef and _Release methods inherited from IInterface. When an object is referenced only through interfaces, there is no need to destroy it manually; the object is automatically destroyed when the last reference to it goes out of scope.

А вообще, прилежным мальчикам положено делать компилятор в соответствии со своей же спецификацией. И работать должно так, как положено. А положено делать финализацию.

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


12-03-2003 18:34
сообщение от автора материала
to MAD:
>Как кстати и положено делать прилежным мальчикам
Пожалуйста приведите цитату из документации, где написано, что так делать необходимо. В свою очередь, цитату, в которой говорится, что интерфейсные ссылки финализируются при выходе из области видимости привожу:

Interface references are managed through reference-counting, which depends on the _AddRef and _Release methods inherited from IInterface. When an object is referenced only through interfaces, there is no need to destroy it manually; the object is automatically destroyed when the last reference to it goes out of scope.

А вообще, прилежным мальчикам положено делать компилятор в соответствии со своей же спецификацией. И работать должно так, как положено. А положено делать финализацию.

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


12-03-2003 16:36
Не совсем страшно.
И типовое решение - вот такое
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,Dialogs;

type
TSomeObject = class(TInterfacedObject,IInterface)
  destructor Destroy; override;
end;

{ TSomeObject }

destructor TSomeObject.Destroy;
begin
  WriteLn("Òèïà äåñòðîé");

  inherited;
end;

var
i:IInterface;
begin
i:=TSomeObject.Create;
i:=nil; //Явно выставим ссылку в nil. Как кстати и положено  
         // делать прилежным мальчикам. :-)
Readln;
end.

Устанавливайте явно ссылки в nil не полагаясь на компилятор. А вообще этот механизм с закадровым колдовством компилятора плохо пахнет.


Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Жили у бабуси два веселых гуся. Один белый, другой КАКОЙ?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования