Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2009.09.06;
Скачать: [xml.tar.bz2];

Вниз

Отложенное освобождение объектов   Найти похожие ветки 

 
ggg   (2008-06-19 19:39) [0]

У меня в программе некоторые объекты имеют счетчик использования. Сделано это для того, что бы они не были удалены до того, когда на них перестанут ссылаться другие объекты.
Сначала пробывал добавить следующий код в деструктор:

destructor TGraphicObject.Destroy;
begin
   if UseCount > 0 then
     begin
       FMustBeFree := true;
       Exit;
     end;
...


Но практически сразу же получал AV.
Поэтому создал метод Free;


procedure TGraphicObject.Free;
begin
 if Assigned(Self) then
   if UseCount > 0 then
     FMustBeFree := true
   else
     inherited; // или Destroy, не важно
end;


Пока вроде бы проблем не наблюдается, но как-то беспокойно на душе :)
Собственно вопросы:
1) Destroy в любом случае удаляет объект, даже если там стоит Exit и не вызывается inherited?
2) Метод Free не помечен как virtual, соответсвенно и мой метод не может быть отмечен как override. Безопасно ли использовать такой способ? Или правильней будет создать некий MyFreeMethod, где будет проверяться FUseCount и вызываться Free?


 
Поросенок Винни-Пух ©   (2008-06-19 20:04) [1]

procedure TGraphicObject.Free;
begin
if Assigned(Self) then

гениально.


 
Поросенок Винни-Пух ©   (2008-06-19 20:05) [2]

А оунер этого волшебного объекта в курсе что кто-то там что-то там считает?

:)


 
Игорь Шевченко ©   (2008-06-19 20:06) [3]

тебе надо посмотреть, как работает TInterfacedObject._Release - оно так примерно и делает, если ссылок 0, то вызывает Destroy

Или переопределить метод FreeInstance


 
Игорь Шевченко ©   (2008-06-19 20:06) [4]

Поросенок Винни-Пух ©   (19.06.08 20:04) [1]


> if Assigned(Self) then
>
> гениально.


Тебе никогда не встречался Self=nil ?


 
Поросенок Винни-Пух ©   (2008-06-19 22:30) [5]

Мне интересно куда он там мог деться в первой же строчке собственного метода, что его проверяют на нил


 
Поросенок Винни-Пух ©   (2008-06-19 22:34) [6]

Сделано это для того, что бы они не были удалены до того, когда на них перестанут ссылаться другие объекты.

То есть есть самодельный механизм подсчета и зачем-то переделываются методы дестрой и фри.

А для чего? Для того, чтобы можно было в любой строчке собственного когда неглядя вызвать фри объекта, не опасаясь что он будет удален если на него есть ссылки?
А не логичнее ли вызывать фри по условию, если уж автору известно есть ссылки или нет их?


 
Loginov Dmitry ©   (2008-06-19 22:53) [7]

> Мне интересно куда он там мог деться в первой же строчке
> собственного метода, что его проверяют на нил



var
 g: TGraphicObject;
begin
 g := nil;
 g.Free;
end;


Что произойдет в g.Free, если if Assigned(Self) не делать?


 
Поросенок Винни-Пух ©   (2008-06-19 22:56) [8]

ты во внутрь самого фри не попадешь при таком раскладе


 
Loginov Dmitry ©   (2008-06-19 23:00) [9]

> ты во внутрь самого фри не попадешь при таком раскладе


Free - это статический метод (фактически обычная процедура). Почему же я в нее не попаду?


 
Anatoly Podgoretsky ©   (2008-06-19 23:09) [10]

> Loginov Dmitry  (19.06.2008 22:53:07)  [7]

А зачем его делать?
Советую взглянуть генофонд или прочитать справку.


 
Поросенок Винни-Пух ©   (2008-06-19 23:14) [11]

Что произойдет в g.Free, если if Assigned(Self) не делать?

Произойдет то же самое, что происходит если делать if Assigned(Self)

g := nil;
g := T...Create();
g.Free;


 
Поросенок Винни-Пух ©   (2008-06-19 23:15) [12]

Нагляднее так:

type
ttt = class
 procedure test;
end;

procedure ttt.test;
begin
 if Assigned(Self) then ShowMessage("yes") else ShowMessage("no");
end;

procedure TForm1.Button1Click(Sender: TObject);
var t : ttt;
begin
t := nil;
t := ttt.Create;
t.Free;
t.test;
end;


 
Loginov Dmitry ©   (2008-06-19 23:16) [13]

> А зачем его делать?


У автора реализован собственный метод Free. В нем выполняется проверка if Assigned(Self). Что произойдет в g.Free (из [7]), если if Assigned(Self) (в TGraphicObject.Free) не делать?


 
Eraser ©   (2008-06-19 23:18) [14]

> [0] ggg   (19.06.08 19:39)


> if Assigned(Self) then
>   if UseCount > 0 then

в данном коде смущает то, что большое количество вложенных условий делает код запутанным.
imho, уместнее
if not Assigned(Self) then
 Exit;


 
Поросенок Винни-Пух ©   (2008-06-19 23:20) [15]

У автора реализован собственный метод Free. В нем выполняется проверка if Assigned(Self). Что произойдет в g.Free (из [7]), если if Assigned(Self) (в TGraphicObject.Free) не делать?

произойдет все то же самое если её делать.


 
Loginov Dmitry ©   (2008-06-19 23:24) [16]

> imho, уместнее
> if not Assigned(Self) then
> Exit;


имхо, нагляднее так:
procedure TGraphicObject.Free;
begin
 if Assigned(Self) then
 begin
   if UseCount > 0 then
     FMustBeFree := true
   else
     inherited; // или Destroy, не важно
 end;
end;


Но у каждого будет свое имхо и спорить, имхо, бессмысленно.


 
Loginov Dmitry ©   (2008-06-19 23:26) [17]

> произойдет все то же самое если её делать.


Для чего тогда, по Вашему, в TObject.Free() реализована такая же проверка?


 
Поросенок Винни-Пух ©   (2008-06-19 23:29) [18]

я ж нарисовал пример в котором assigned рапортует "yes"
и типа после этого метод уверен, что можно что-то там делать.


 
Loginov Dmitry ©   (2008-06-19 23:55) [19]

> я ж нарисовал пример в котором assigned рапортует "yes"
> и типа после этого метод уверен, что можно что-то там делать.


совать во Free() битые ссылки - ситуация ненормальная и естественно карается. А вот вызов TObject(nil).Free - это обычное дело, и без проверки на nil не обойтись.


 
ggg   (2008-06-20 06:03) [20]

>> [1]
system.pas

procedure TObject.Free;
begin
 if Self <> nil then
   Destroy;
end;

Вы считаете это глупость?

>> [3]
FreeInstance вызывается после Destroy, но если проверку добавить в оба метода, то да. Спасибо, помогло :)

>> [6]
Да, иметь возможность вызвать метод Free в любой момент не заботясь о последствиях весьма удобно.
Заменить это уменьшением UseCount.. не безопасно. Просто, возможно несколько условий на различных стадиях работы движка, когда объект необходимо удалить. Тогда при выполнении нескольких условий счетчик может стать равным 0 до того, как объект действительно освободится.

>>[14]
Где-то встречал, будто опыты показали, что if...else работает быстрее, чем Exit. Не ручаюсь за достоверность, но большой разницы нет.

>>[16]
Насколько мне известно, эти begin..end дадут несколько другой код после компиляции, который будет выполнятся дольше. Хотя, возможно, это предрассудки моего препода по паскалю :)


 
Loginov Dmitry ©   (2008-06-20 07:50) [21]

> Насколько мне известно, эти begin..end дадут несколько другой
> код после компиляции, который будет выполнятся дольше


Разговор про наглядность, а не про скорость. Скорость тут дело десятое.


> Хотя, возможно, это предрассудки моего препода по паскалю
> :)


+1 :)


 
Игорь Шевченко ©   (2008-06-20 09:44) [22]


> ты во внутрь самого фри не попадешь при таком раскладе


я попаду в любой невиртуальный метод


 
ggg   (2008-06-20 20:06) [23]

Ну как бы всё-равно проблемы остались -- одну и ту же проверку приходится производить дважды: в Destroy и в FreeInstance. Если есть еще предложения, буду рад выслушать.


 
Eraser ©   (2008-06-20 20:54) [24]

> [20] ggg   (20.06.08 06:03)


> Где-то встречал, будто опыты показали, что if...else работает
> быстрее, чем Exit. Не ручаюсь за достоверность, но большой
> разницы нет.

ох уж эта привычка применять тонкую оптимизацию где попало, а потом разгребаешь
if then
 if then
  if then

и еще тележку else if



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

Форум: "Основная";
Текущий архив: 2009.09.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.007 c
15-1246918524
DVM
2009-07-07 02:15
2009.09.06
Функция обратного вызова с переменным числом параметров.


15-1245787291
Игорь Шевченко
2009-06-24 00:01
2009.09.06
Дядя Юра, с днем рождения!


2-1247039063
MAX
2009-07-08 11:44
2009.09.06
из Word в БД


4-1216586310
batya-x
2008-07-21 00:38
2009.09.06
поск файлов на winAPI


15-1246518647
stas
2009-07-02 11:10
2009.09.06
3D фото





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский