![]() |
|
Модераторы: Poseidon, Snowy, bems, MetalFan |
![]()
|
|
| Nloge |
|
||||||
![]() Новичок Профиль Группа: Участник Сообщений: 34 Регистрация: 25.3.2002 Репутация: нет Всего: нет |
Пусть у меня есть некий класс, у которого одно из полей динамический массив. Как правильно уничтожить экземпляр этого класса? Поясню почему возник этот вопрос.
Обычно для освобождения динамического массива досточно всем ссылкам на этот динамический массив присвоить nil. То есть:
Тут память освободиться после строки {2}. Поэтому обычно если я описываю что-то типа этого :
то обязательно добавляю в деструкторе TmyClass строку в которой присваивается полю arr значение nil. А тут вот задумался - а нужно ли это делать? Ведь описание приведеного arr по сути тождественна описанию поля типа string. А для string я никогда в деструкторе не пишу присвоение пустой строки и вроде это не нужно (так?). Еще интереснее получается при определении поля вот такого типа:
какой тут должен быть деструктор? Или такое поле вообще не надо никак очищать? |
||||||
|
|||||||
| Fantasist |
|
|||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: нет Всего: 41 |
Help Delphi утверждает, что для освобожение памяти динамическаго массива, нужно переменным присвоить nil или передать как параметр Finalize.
-------------------- Волны гасят ветер... |
|||
|
||||
| Nloge |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 34 Регистрация: 25.3.2002 Репутация: нет Всего: нет |
Кстати... Примерно такой же вопрос у меня и по интерфейсам. Они имеют тоже свойство что и динамические массивы - для освобождения ресурсов связанных с интерфейсом, нужно всем ссылкам на этот интерфейс присвоить значение nil.
- Если у меня в классе есть поле - ссылка на интерфейс, надо ли мне в деструкторе присваивать nil этому полю? - А если у меня в классе есть поле массив ссылок на интерфейсы? - А если этот массив динамический? :-) |
|||
|
||||
| Fantasist |
|
|||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: нет Всего: 41 |
Кто это вам такое сказал? Переменная, имеющая тип interface - это всего лишь УКАЗАТЕЛЬ на таблицу методов какого-то объекта. Никаких дополнительных ресурсов эта переменная не занимает. Читайте мою статью о COM, я там это вроде достаточно наглядно показываю. -------------------- Волны гасят ветер... |
|||
|
||||
| Vit |
|
|||
![]() 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 |
|||
|
||||
| Nloge |
|
||||||||||
![]() Новичок Профиль Группа: Участник Сообщений: 34 Регистрация: 25.3.2002 Репутация: нет Всего: нет |
Это утверждение не верно.
Тут сформулировано точнее, но опять-таки не совсем правильное утверждение. Ниже я постараюсь объяснить почему.
Память освобождается - это совершенно точно. Поскольку написано в help`е(на что указал Fantasist). Да и проверил я это полазив по исходникам и окушку CPU
Чарльз Калверт. стр 359 его книги Delphi4 Энциклопедия пользователя. глава "разрушение интерфейсов". Цитаты:
Далее я своими словами... Дело в том, что хотя интерфейсы это просто указатели, но они указатели на объекты. Если покопаться то там выясняется что это не просто указатели. Важно что когда мы создаем интерфейс, то мы связываем его с неким объектом (который создается явно или нет, при этом забирая-таки ресурсы) и при присваивании интерфейсу значения nil этот объект автоматически разрушается (если на него нет других ссылок). Тоже происходит и при выходе объекта их области видимости. Примерно также ведет себя и динамический массив. И интерфейс и динамический массив, это "умные указатели", кроме самого адреса, на который они указывают, они содержат еще и информацию о количестве ссылок которые ссылаються на этот участок памяти. Когда число это ссылок становиться = 0 объект, на который они ссылаються, разрушается. Точно также ведет себя тип string. Проблема тут только одна - как определяется выход из области видимости. Когда есть процедура и в ней локально определен такой "умный указатель", то все просто - вышли из процедуры, указатель обнулился автоматически. А если есть глобальные классы, которые разрушаються и создаються когда угодно и содержат указатели друг на друга то тут начинается путаница... Надо будет мне поразбираться с этим как-нибудь повнимательнее... |
||||||||||
|
|||||||||||
| Vit |
|
|||
![]() 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 |
|||
|
||||
| Vit |
|
||||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 48 Всего: 207 |
Это утверждение верно! Объект на который указывает интерфейс не создается в приложении. Например у нас есть 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 |
||||
|
|||||
| Fantasist |
|
|||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: нет Всего: 41 |
Вы бы прежде чем так утверждать, ознакомились бы с вопросом. К сожалению, почерпнутая Вами из какой-то книги цитата не объясняет Вам многого, а возможно запутывает. Все что сказанно Вами после слов "Далее моими словами..." не корректно, а то и просто ошибочно. Представте себе, что вы написалт COM объект на Delphi, а потом кто-то пытается использовать его в другом языке программирования. Следуя стандарту, он получит указатель на интерфейс и будет с ним работать как с указателем! Подчиняясь правилам пользования интерфейсом. А то и просто загляните в TObject.GetInterface, слава богу, исходники есть. Там возвращается просто указатель полученный из таблицы интерфейсов, и ничего более. Далее. Термин "умные указатели" пришел не отсюда, и означает несколько иное. Обычно это класс, который конструирует динамический объект и удаляет его. Сам такой класс помещают в стеке, что позволяет избежать случайных потерь памяти, или потерю ее при исключениях. То, что происходит в Delphi при присвоении nil динамическому массиву, обычно называют механизмом сборки мусора - когда автоматически освобождается памяти из под неиспользуемых объектов без явного указания пользователя. Если такое поддерживается для интерфейсов, то это извращение и я никогда не советую это использовать - очень черевато конфликтами да и не красиво это. -------------------- Волны гасят ветер... |
|||
|
||||
| Nloge |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 34 Регистрация: 25.3.2002 Репутация: нет Всего: нет |
Так сказать оправдание
Sorry, я не точно (в очередной раз) выразился в результате вы не поняли, что я хотел сказать. Я ни в коей мере не имел ввиду, что нужно вручную удалять объект на который ссылается интерфейс. Я хотел просто указать на то, что в случае когда этот объект уже в программе не нужен то имеет смысл освободить сам интерфейс, путем присваивания ему nil. При этом если ссылок на объект больше нет (не только в моей программе, а вообще во всех запущенных приложениях) то объект автоматически будет уничтожен. Действительно что-то типа "сборки мусора" ("умный указатель" в самом деле был упомянут мной не коректно). Только она отоситься не к отдельному приложению, а ко всей системе в целом. Конечено можно и не присваивать интерфейсу этот самый nil, и тогда счеткик указателей на объект связанный с интерфейсом уменьшиться при выходе программы из области видимости переменной-интерфейса. Но если у нас переменная-интерфейс объявлена глобально, то это значит что счетчик уменьшиться при завершении работы программы. То есть, допустим нам временно нужен был эксплорер и мы получили к нему доступ через интерфейс, сделали пару операций и забыли про него. Опять-таки допустим, другие программы не используют этот объект. В этом случае эксплорер все равно будет висеть в памяти (никому не нужный), отнимая ресурсы, пока наша программа не завершиться. Теперь я нигде не ошибаюсь? |
|||
|
||||
| Vit |
|
|||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 48 Всего: 207 |
Пришли к консенсусу
Не уверен, что присвоение интерфейсу Nil приведет к выгрузке из памяти COM, даже если его никто не использует, к сожалению винды еще и кэшируют загрузку объектов и по моему опыту, часто используемые объекты не выгружаются -------------------- 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 |
|||
|
||||
| Fantasist |
|
|||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: нет Всего: 41 |
По стандарту COM, счетчик должен уменьшаться за счет вызова Release.
Я посмотрел, действительно Delphi вызывает Release за тебя, в случае если переменной интерфейсного типа присвоить nil или при ее уничтожении(я имею ввиду, если она(переменная) стековая. Динасические не проверял). Однако естественно, что если вы сохраните указатель на интерфейс НЕ в интерфейсной переменной, а в pointer например, то ничего такого не произойдет. В любом случае, как я уже сказал, мне такой путь не нравиться. Это, конечно, может быть удобно, однако если вы придете в проффесиональное общество - это могут не одобрить. Стандарт - он на то и есть стандарт. -------------------- Волны гасят ветер... |
|||
|
||||
![]()
|
| Правила форума "Delphi: Общие вопросы" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |