Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.11.18;
Скачать: CL | DM;

Вниз

Почему освобождённые объекты не ссылаются на nil   Найти похожие ветки 

 
alex_ant ©   (2007-10-21 17:50) [0]

Внутри объекта используются ещё 3 однотипных объекта, реализация которых была реализована не мной (она закрыта от меня). В деструкторе своего объекта я освобождаю их:

destructor TMyObj.Destroy();
begin
 OtherObj1.Free();
 OtherObj3.Free();
 OtherObj3.Free();
end;

После вызова Free(), внутри деструктора, эти объекты начинают ссылаться на nil, и всё вроде бы логично. Но извне, некоторые объекты оказываются неравны nil.

MyObj.Destroy(); //Внутри после освобождения все в nil
//Тут эти подобъекты уже не равны nil
if (MyObj.OtherObj1 = nil) and (MyObj.OtherObj2 = nil) and (MyObj.OtherObj3 = nil) then
 ShowMessage("Объекты ссылаются на nil")
else
 ShowMessage("Объекты НЕ ссылаются на nil");

У меня всегда выводит «Объекты НЕ освободились». Причём средний объект равен nil, но другие ссылаются куда-то.

Сразу говорю, что вызываю MyObj.Destroy() вместо рекомендованного MyObj.Free(), чтобы проверить правильность освобождения подобъектов (этот вызов производится в тестах).

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

Заранее благодарю за советы.

P. S. Дочерние объекты, реализованные не мной, предоставляет платный пакет одной крутой фирмы, так что ошибки в них крайне маловероятны.


 
DrPass ©   (2007-10-21 17:57) [1]


> Так вот вопрос: нормальное ли это поведение

Да, нормальное. Free вызывает деструктор и разрушает объект. Но переменную, естественно, в nil ты должен сам установить.


 
alex_ant ©   (2007-10-21 18:13) [2]


> Да, нормальное. Free вызывает деструктор и разрушает объект.
>  Но переменную, естественно, в nil ты должен сам установить.


Да, но они уже установленны в nil внутри деструктора. Я проверял.

Кроме того, это первое что я испробовал: после освобождения сам установил всё в nil:

destructor TMyObj.Destroy();
begin
 OtherObj1.Free();
 OtherObj3.Free();
 OtherObj3.Free();
 OtherObj1 := nil;
 OtherObj3 := nil;
 OtherObj3 := nil;
end;

Но... ситуация не изменилась. Описываемый мной глюк остался. Как такое может быть???


 
Jump   (2007-10-21 18:17) [3]

OtherObj1.Free();
OtherObj3.Free();
OtherObj3.Free();
OtherObj1 := nil;
OtherObj3 := nil;
OtherObj3 := nil;


Давай, поставь двоечку...


 
Однокамушкин   (2007-10-21 19:05) [4]


> MyObj.Destroy(); //Внутри после освобождения все в nil
> //Тут эти подобъекты уже не равны nil
> if (MyObj.OtherObj1 = nil) and (MyObj.OtherObj2 = nil) and
> (MyObj.OtherObj3 = nil) then

Очень грубая ошибка - сначала делаете MyObj.Destroy, а потом обращаетесь к MyObj... Правило, которому нужно следовать неукоснительно: вызвали Destroy (или Free) - всё, забыли про такой объект, никаких обращений к нему


 
Leonid Troyanovsky ©   (2007-10-21 19:18) [5]


> alex_ant ©   (21.10.07 18:13) [2]

> Кроме того, это первое что я испробовал: после освобождения
> сам установил всё в nil

MyObj.OtherObj1 <> OtherObj1

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-10-21 19:19) [6]


> Jump   (21.10.07 18:17) [3]

> Давай, поставь двоечку...

Легко.

--
Regards, LVT.


 
alex_ant ©   (2007-10-21 20:04) [7]


> Jump   (21.10.07 18:17) [3]
> Давай, поставь двоечку...

Да это я в примере ошибся, на самом деле имена у всех осмысленные и ошибка точно не в этом.


> Однокамушкин   (21.10.07 19:05) [4]
> Очень грубая ошибка - сначала делаете MyObj.Destroy, а потом
> обращаетесь к MyObj... Правило, которому нужно следовать
> неукоснительно: вызвали Destroy (или Free) - всё, забыли
> про такой объект, никаких обращений к нему

А как узнать, что память освободилась корректно? Я в общем-то так всегда и поступал, а тут решил проверить производится ли правильное освобождение...


> Leonid Troyanovsky ©   (21.10.07 19:18) [5]
> MyObj.OtherObj1 <> OtherObj1

Ну допустим, а вывод какой? Почему некторые MyObj.OtherObj равны nil, а некоторые не равны?


 
Leonid Troyanovsky ©   (2007-10-21 20:40) [8]


> alex_ant ©   (21.10.07 20:04) [7]

> Ну допустим, а вывод какой? Почему некторые MyObj.OtherObj
> равны nil, а некоторые не равны?

Допустим что MyObj = MyObj1 = .. = MyObjN.
Присвоим MyObj := nil,
чему будет равен MyObjX.

--
Regards, LVT.


 
Плохиш ©   (2007-10-21 21:19) [9]


> Почему некторые MyObj.OtherObj равны nil, а некоторые не
> равны?

Потому что "мусор" может быть nil, а может и не быть...


 
alex_ant ©   (2007-10-21 22:14) [10]


> Плохиш ©   (21.10.07 21:19) [9]
> Потому что "мусор" может быть nil, а может и не быть...

А... круто! :) Резонное замечание, что-то раньше я не додумался... :)))


 
vpbar ©   (2007-10-21 22:42) [11]

>> Так вот вопрос: нормальное ли это поведение
Да, нормальное. Free вызывает деструктор и разрушает объект. Но переменную, естественно, в nil ты должен сам установить. (c) [1]

>>Да, но они уже установленны в nil внутри деструктора. Я проверял.
В каком деструкторе?
Если в этом
destructor TMyObj.Destroy();
begin
OtherObj1.Free();
OtherObj2.Free();
OtherObj3.Free();
OtherObj1 := nil;
OtherObj2 := nil;
OtherObj3 := nil;
end;

То переменные OtherObj1 ... OtherObj3 должны быть равны nil, если только после этого им ничего не присваивать.

Если имеется ввиду дестрктор который вызывается в например, OtherObj1.Free() то он ничего о OtherObj1 не знает. Ему в eax передается указатель на объект (это тот же указатель который хранится в OtherObj1, но не сам OtherObj1) который он и освобождает.


 
Юрий Зотов ©   (2007-10-22 00:22) [12]

> alex_ant ©   (21.10.07 17:50)  

> Почему освобождённые объекты не ссылаются на nil [D7, WinXP]

Жил человек. Его адрес (или телефон) был записан у N других людей. Причем он даже и сам не знает, у кого именно. И даже чему равно N - он тоже не знает. И никто этого не знает.

Человек умер. А что стало с этими самыми N записями?

Они исчезли? Нет. Ведь их никто не уничтожал.

Они изменились? Нет. Ведь их никто не менял.

Они остались точно такими же, какими и были. Но стали неправильными. Потому что этот человек по этому адресу более не живет.

Аналогию чувствуете? В программе было N ссылок на один и тот же объект. Сам объект об этих ссылках, естественно, ничего не знает. И даже не знает, есть ли они вообще и сколько их.

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

Эти ссылки остались точно такими же, какими и были. Но стали неправильными. Потому что этот объект по этому адресу более не живет.


 
Германн ©   (2007-10-22 00:46) [13]

Нет повести печальнее на свете, чем повесть о разрушенном объекте :(


 
Джо ©   (2007-10-22 03:16) [14]

> [13] Германн ©   (22.10.07 00:46)
> Нет повести печальнее на свете, чем повесть о разрушенном
> объекте :(

Хао! даже рука не поднимается назвать это «оффтопом».


 
Германн ©   (2007-10-22 04:27) [15]


> даже рука не поднимается назвать это «оффтопом».
>  
А с чего бы именно рука поднялась бы? :-)
Уж сколько раз твердили миру, но всё равно. The gods themselves contains in vain :)


 
alex_ant   (2007-10-22 12:15) [16]


> Юрий Зотов ©   (22.10.07 00:22) [12]
> Жил человек. Его адрес (или телефон) был записан у N других
> людей. Причем он даже и сам не знает, у кого именно. И даже
> чему равно N - он тоже не знает. И никто этого не знает.

Спасибо очень понятное такое сравнение. :)

Нашел вот интересную статью по теме:
http://softwarer.ru/memory.html

Понятно теперь, что переменная освобождённого объекта не обязательно ссылается на nil, но вопрос можно ли проверить правильность деструктора (что все подобъекты освободились полностью) остался так и неясен...

Ведь объекты живут вне зависимости от того, есть ли на них ссылка, и если родительский объект умер, дочерний может ещё засорять память... В общем-то затею с nil, я начал именно, чтобы научиться проверять освобождение подобъектов... а как это сделать, теперь тем более не ясно.


 
Ins ©   (2007-10-22 12:21) [17]


> Ведь объекты живут вне зависимости от того, есть ли на них
> ссылка, и если родительский объект умер, дочерний может
> ещё засорять память..

Нужно просто при уничтожении т.н. родительского объекта, уничтожать дочерний. И не нужно ни за чем следить. Если сами для него (дочернего) Free в деструкторе родительского вызовите - расслабьтесь и получайте удовольствие.


 
Сергей М. ©   (2007-10-22 12:27) [18]


> вопрос можно ли проверить правильность деструктора (что
> все подобъекты освободились полностью) остался так и неясен


Если ты вызвал метод Free некоего объекта и при этом не схлопотал исключение, можешь практически со 100%-ной уверенностью считать, что этот объект тобой уничтожен.


 
Ins ©   (2007-10-22 12:39) [19]


> alex_ant ©   (21.10.07 17:50)

Вы случайно не Алексей Федоров? :)


 
alex_ant   (2007-10-22 12:47) [20]


> Ins ©   (22.10.07 12:39) [19]
> Вы случайно не Алексей Федоров? :)

Он самый. Не только я, значит, на два фронта работаю. :)))


> Сергей М. ©   (22.10.07 12:27) [18]
> Если ты вызвал метод Free некоего объекта и при этом не
> схлопотал исключение, можешь практически со 100%-ной уверенностью
> считать, что этот объект тобой уничтожен.

А если я сделал 3 подобъекта, и по невнимательности освободил только 2. Память будет засорена. Могу ли я проверить как-то программно, что я забыл освободить третий подобъект?


 
Сергей М. ©   (2007-10-22 12:52) [21]


> если я сделал 3 подобъекта, и по невнимательности освободил
> только 2


Будь внимательней и освобождай все 3.

А если лениво освобождать "ручками", сделай все свои объекты наследниками TComponent, тогда все упрощается (см. справку "Owner property (TComponent)")


 
Slym ©   (2007-10-22 12:53) [22]

alex_ant   (22.10.07 12:47) [20]
по невнимательности

Микрасофт тоже в основном по "невнимательности", а потом патчи делает и ничего :)
Память будет засорена
Я бы сказал потеряна, и не всегда только память: у системы многа разных ресурсов (хендлы, GDI  и пр.)


 
homm ©   (2007-10-22 12:53) [23]

> [20] alex_ant   (22.10.07 12:47)
> А если я сделал 3 подобъекта, и по невнимательности освободил
> только 2. Память будет засорена. Могу ли я проверить как-
> то программно, что я забыл освободить третий подобъект?

Можешь программно, но лучше аппаратно, освободить там, где забыл.


 
alex_ant   (2007-10-22 12:53) [24]

В общем, спасибо всем за помощь. Ins на путь истинный направил. :)


 
Ins ©   (2007-10-22 12:56) [25]


> А если лениво освобождать "ручками", сделай все свои объекты
> наследниками TComponent, тогда все упрощается (см. справку
> "Owner property (TComponent)")

Да много вариантов, на самом деле... заносить в TObjectList, наследовать от TComponent или TInterfacedObject... Выбирай на вкус.


 
vpbar ©   (2007-10-22 13:23) [26]

Ага. Еще вариант перейти в net, где все ссылаки на счету. Или в делфи с объектами работать через интерфейсы


 
Anatoly Podgoretsky ©   (2007-10-22 16:34) [27]

> alex_ant  (22.10.2007 12:47:20)  [20]

Никогда так не делай, это не программа, а ужас.


 
Anatoly Podgoretsky ©   (2007-10-22 16:35) [28]

> Slym  (22.10.2007 12:53:22)  [22]

Что позволено Юпитеру, не позволено быку, кроме того у них Дельфи нет.


 
alex_ant   (2007-10-22 17:10) [29]


> Сергей М. ©   (22.10.07 12:52) [21]
> Будь внимательней и освобождай все 3.

Да я внимательный, просто есть ещё тесты модулей для обострения внимательности. Их использование для этой задачи и хотел изучить.


 
Сергей М. ©   (2007-10-22 17:15) [30]


> есть ещё тесты модулей для обострения внимательности


Нафига человеку со зрением 1.0 на оба глаза носить очки с диоптриями ?)


 
alex_ant ©   (2007-10-22 21:17) [31]


> Сергей М. ©   (22.10.07 17:15) [30]
> Нафига человеку со зрением 1.0 на оба глаза носить очки
> с диоптриями ?)

Это философский вопрос. Все у кого железная внимательность, давно строчат гуёвые приложения в машинных кодах. :) Люди попроще пишут в Delphi, ещё и тестами модулей...



Страницы: 1 вся ветка

Текущий архив: 2007.11.18;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.016 c
15-1192174488
Azize
2007-10-12 11:34
2007.11.18
Web технологии и поддержка


2-1193534997
San1712
2007-10-28 04:29
2007.11.18
Как удалить запись типа TSearchRec ?


2-1193516773
Игорь
2007-10-28 00:26
2007.11.18
SAPI 4


2-1193467708
VladimirK
2007-10-27 10:48
2007.11.18
Экспорт в MS Excel


15-1192190259
Cyrax
2007-10-12 15:57
2007.11.18
Дистрибьютеры, дилеры и ремонт техники в сервисных центрах...