Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> освобождение динамических массивов 
:(
    Опции темы
Nloge
  Дата 2.4.2002, 07:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 34
Регистрация: 25.3.2002

Репутация: нет
Всего: нет



Пусть у меня есть некий класс, у которого одно из полей динамический массив. Как правильно уничтожить экземпляр этого класса? Поясню почему возник этот вопрос.
Обычно для освобождения динамического массива досточно всем ссылкам на этот динамический массив присвоить nil.
То есть:
Код

var arr1,arr2 : array of byte;
    i            : integer;
begin
 SetLength(arr1,10);
 for i := low(arr1) to high(arr1) do
    arr1[i] := i;
 
 arr2 := arr1;
 arr1 := nil;  {1}
 arr2 := nil;  {2}
end;

Тут память освободиться после строки {2}.
Поэтому обычно если я описываю что-то типа этого :
Код

 type TmyClass = class
            ....
            arr : array of byte;
          end;

то обязательно добавляю в деструкторе TmyClass строку в которой присваивается полю arr значение nil.
А тут вот задумался - а нужно ли это делать? Ведь описание приведеного  arr по сути тождественна описанию поля типа string. А для string я никогда в деструкторе не пишу присвоение пустой строки  и вроде это не нужно (так?). Еще интереснее получается при определении поля вот такого типа:
Код

  type TArr = array of integer;
  type TRec = record
                    name : string;
                    arr    : TArr;
                   end;
  type TmyClass = class
           arr : array of TRec;
           .......  
           end;

какой тут должен быть деструктор? Или такое поле вообще не надо никак очищать?
PM MAIL ICQ   Вверх
Fantasist
Дата 2.4.2002, 08:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: нет
Всего: 41



Help Delphi утверждает, что для освобожение памяти динамическаго массива, нужно переменным присвоить nil или передать как параметр Finalize.


--------------------
Волны гасят ветер...
PM MAIL   Вверх
Nloge
Дата 2.4.2002, 08:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 34
Регистрация: 25.3.2002

Репутация: нет
Всего: нет



Кстати... Примерно такой же вопрос у меня и по интерфейсам. Они имеют тоже свойство что и динамические массивы - для освобождения ресурсов связанных с интерфейсом, нужно всем ссылкам на этот интерфейс присвоить значение nil.
- Если у меня в классе есть поле - ссылка на интерфейс, надо ли мне в деструкторе присваивать nil этому полю?
- А если у меня в классе есть поле массив ссылок на интерфейсы?
- А если этот массив динамический? :-)
PM MAIL ICQ   Вверх
Fantasist
Дата 2.4.2002, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: нет
Всего: 41



Цитата
Примерно такой же вопрос у меня и по интерфейсам. Они имеют тоже свойство что и динамические массивы - для освобождения ресурсов связанных с интерфейсом, нужно всем ссылкам на этот интерфейс присвоить значение nil.


Кто это вам такое сказал?
Переменная, имеющая тип interface - это всего лишь УКАЗАТЕЛЬ на таблицу методов какого-то объекта. Никаких дополнительных ресурсов эта переменная не занимает.
Читайте мою статью о COM, я там это вроде достаточно наглядно показываю.


--------------------
Волны гасят ветер...
PM MAIL   Вверх
Vit
Дата 2.4.2002, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vitaly Nevzorov
****


Профиль
Группа: Экс. модератор
Сообщений: 10964
Регистрация: 25.3.2002
Где: Chicago

Репутация: 48
Всего: 207



Динамические массивы можно легко удалить из памяти установив их длину в ноль функцией SetLength. Интерфейсы не нуждаются в освобождении памяти - это только указатель, реально никаких структур в приложении не создается. По поводу установки массива в Nil - берут меня сомнения, как бы при этом не заставить просто массив показывать в никуда, а сами данные массива могу остаться в памяти - я неуверен может кто-то знает лучше?


--------------------
With the best wishes, Vit
I have done so much with so little for so long that I am now qualified to do anything with nothing
Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru
PM MAIL WWW ICQ   Вверх
Nloge
Дата 3.4.2002, 02:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 34
Регистрация: 25.3.2002

Репутация: нет
Всего: нет



Цитата

Интерфейсы не нуждаются в освобождении памяти - это только указатель, реально никаких структур в приложении не создается

Это утверждение не верно.

Цитата

Переменная, имеющая тип interface - это всего лишь УКАЗАТЕЛЬ на таблицу методов какого-то объекта. Никаких дополнительных ресурсов эта переменная не занимает.

Тут сформулировано точнее, но опять-таки не совсем правильное утверждение. Ниже я постараюсь объяснить почему.

Цитата

По поводу установки массива в Nil - берут меня сомнения, как бы при этом не заставить просто массив показывать в никуда, а сами данные массива могу остаться в памяти - я неуверен может кто-то знает лучше?

Память освобождается - это совершенно точно. Поскольку написано в help`е(на что указал Fantasist). Да и проверил я это полазив по исходникам и окушку CPU :) (help тоже бывает врет). А вот установка размера равного в 0, хотя и делает тоже самое(я ей до последнего времени тоже пользовался), но  в help`е не упомянута...

Цитата
Кто это вам такое сказал?

Чарльз Калверт. стр 359 его книги Delphi4 Энциклопедия пользователя.
глава "разрушение интерфейсов".
Цитаты:
Цитата

Интерфейс не должен разрушаться, поскольку Delphi делает это автоматически.
....skip....
Все это хорошо и прекрасно, но что делать если требуется явно уничтожить объект?
....skip....
Коректный способ разрушения этих объектов заключается в том, чтобы установить их равными nil:
 MyInterface := nil;

Далее я своими словами...
Дело в том, что хотя интерфейсы это просто указатели, но они указатели на объекты. Если покопаться то там выясняется что это не просто указатели. Важно что когда мы создаем интерфейс, то мы связываем его с неким объектом (который создается явно или нет, при этом забирая-таки ресурсы) и при присваивании интерфейсу значения nil этот объект автоматически разрушается (если на него нет других ссылок). Тоже происходит и при выходе объекта их области видимости. Примерно также ведет себя и динамический массив. И интерфейс и динамический массив, это "умные указатели", кроме самого адреса, на который они указывают, они содержат еще и информацию о количестве ссылок которые ссылаються на этот участок памяти. Когда число это ссылок становиться = 0 объект, на который они ссылаються, разрушается.
Точно также ведет себя тип string.
Проблема тут только одна - как определяется выход из области видимости. Когда есть процедура и в ней локально определен такой "умный указатель", то все просто - вышли из процедуры, указатель обнулился автоматически. А если есть глобальные классы, которые разрушаються и создаються когда угодно и содержат указатели друг на друга то тут начинается путаница... Надо будет мне поразбираться с этим как-нибудь повнимательнее...
PM MAIL ICQ   Вверх
Vit
Дата 3.4.2002, 03:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vitaly Nevzorov
****


Профиль
Группа: Экс. модератор
Сообщений: 10964
Регистрация: 25.3.2002
Где: Chicago

Репутация: 48
Всего: 207



Мда! Умная система, чего-то сама делает, чего-то нет...


--------------------
With the best wishes, Vit
I have done so much with so little for so long that I am now qualified to do anything with nothing
Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru
PM MAIL WWW ICQ   Вверх
Vit
Дата 3.4.2002, 05:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vitaly Nevzorov
****


Профиль
Группа: Экс. модератор
Сообщений: 10964
Регистрация: 25.3.2002
Где: Chicago

Репутация: 48
Всего: 207



Цитата(Nloge @ 02.4.2002, 17:26)
Цитата

Интерфейсы не нуждаются в освобождении памяти - это только указатель, реально никаких структур в приложении не создается

Это утверждение не верно.

Это утверждение верно! Объект на который указывает интерфейс не создается в приложении. Например у нас есть 10 разных приложений которые используют один и тот же интерфейс - объект же на который указывает интерфейс существует в памяти в одном экземпляре, и счетчик ссылок ведется тоже глобальный в отличие от Strings и динамических массивов которые существуют только в приложении. Следовательно попытка раздушения самого СОМ объекта в контексте одного приложения не имеет смысла и потенциально опасна крахом других приложений - например у вас когда нибудь вылетал IE по General Protection? Ведь в результате обрушиваются все открытые экземпляры IE! Или я не прав? Может я не совсем правльно понимаю эти механизмы?


--------------------
With the best wishes, Vit
I have done so much with so little for so long that I am now qualified to do anything with nothing
Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru
PM MAIL WWW ICQ   Вверх
Fantasist
Дата 3.4.2002, 07:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: нет
Всего: 41



Цитата
Это утверждение не верно.


Вы бы прежде чем так утверждать, ознакомились бы с вопросом. К сожалению, почерпнутая Вами из какой-то книги цитата не объясняет Вам многого, а возможно запутывает. Все что сказанно Вами после слов "Далее моими словами..." не корректно, а то и просто ошибочно.

Представте себе, что вы написалт COM объект на Delphi, а потом кто-то пытается использовать его в другом языке программирования. Следуя стандарту, он получит указатель на интерфейс и будет с ним работать как с указателем! Подчиняясь правилам пользования интерфейсом. А то и просто загляните в TObject.GetInterface, слава богу, исходники есть. Там возвращается просто указатель полученный из таблицы интерфейсов, и ничего более.

Далее. Термин "умные указатели" пришел не отсюда, и означает несколько иное. Обычно это класс, который конструирует динамический объект и удаляет его. Сам такой класс помещают в стеке, что позволяет избежать случайных потерь памяти, или потерю ее при исключениях. То, что происходит в Delphi при присвоении nil динамическому массиву, обычно называют механизмом сборки мусора - когда автоматически освобождается памяти из под неиспользуемых объектов  без явного указания пользователя. Если такое поддерживается для интерфейсов, то это извращение и я никогда не советую это использовать - очень черевато конфликтами да и не красиво это.


--------------------
Волны гасят ветер...
PM MAIL   Вверх
Nloge
Дата 4.4.2002, 11:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 34
Регистрация: 25.3.2002

Репутация: нет
Всего: нет



Так сказать оправдание :)
Sorry, я не точно (в очередной раз) выразился в результате вы не поняли, что я хотел сказать.
Я ни в коей мере не имел ввиду, что нужно вручную удалять объект на который ссылается интерфейс. Я хотел просто указать на то, что в случае когда этот объект уже в программе не нужен то имеет смысл освободить сам интерфейс, путем присваивания ему nil. При этом если ссылок на объект больше нет (не только в моей программе, а вообще во всех запущенных приложениях) то объект автоматически будет уничтожен. Действительно что-то типа "сборки мусора" ("умный указатель" в самом деле был упомянут мной не коректно). Только она отоситься не к отдельному приложению, а ко всей системе в целом.
Конечено можно и не присваивать интерфейсу этот самый nil, и тогда счеткик указателей на объект связанный с интерфейсом уменьшиться при выходе программы из области видимости переменной-интерфейса. Но если у нас переменная-интерфейс объявлена глобально, то это значит что счетчик уменьшиться при завершении работы программы. То есть, допустим нам временно нужен был эксплорер и мы получили к нему доступ через интерфейс, сделали пару операций и забыли про него. Опять-таки допустим, другие программы не используют этот объект. В этом случае эксплорер все равно будет висеть в памяти (никому не нужный), отнимая ресурсы, пока наша программа не завершиться.
Теперь я нигде не ошибаюсь?
PM MAIL ICQ   Вверх
Vit
Дата 4.4.2002, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vitaly Nevzorov
****


Профиль
Группа: Экс. модератор
Сообщений: 10964
Регистрация: 25.3.2002
Где: Chicago

Репутация: 48
Всего: 207



Пришли к консенсусу :)
Не уверен, что присвоение интерфейсу Nil приведет к выгрузке из памяти COM, даже если его никто не использует, к сожалению винды еще и кэшируют загрузку объектов и по моему опыту, часто используемые объекты не выгружаются :(  , но учитывая что создания 2х объектов невозможно утечки памяти не предвидится...


--------------------
With the best wishes, Vit
I have done so much with so little for so long that I am now qualified to do anything with nothing
Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru
PM MAIL WWW ICQ   Вверх
Fantasist
Дата 4.4.2002, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: нет
Всего: 41



По стандарту COM, счетчик должен уменьшаться за счет вызова Release.
Я посмотрел, действительно Delphi вызывает Release за тебя, в случае если переменной интерфейсного типа присвоить nil или при ее уничтожении(я имею ввиду, если она(переменная) стековая. Динасические не проверял). Однако естественно, что если вы сохраните указатель на интерфейс НЕ в интерфейсной переменной,  а в pointer например, то ничего такого не произойдет. В любом случае, как я уже сказал, мне такой путь не нравиться. Это, конечно, может быть удобно, однако если вы придете в проффесиональное общество - это могут не одобрить. Стандарт - он на то и есть стандарт.


--------------------
Волны гасят ветер...
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0538 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.