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

Вниз

Вызов Free (Destroy) внутри метода объекта   Найти похожие ветки 

 
pasha_golub ©   (2009-08-03 18:36) [0]

Тут сабжевый холливорчик завязался. Ситуация:

procedure SomeProc;
begin
<do smth>;
if SomeIllegalCondition then Free;
end;


Моя позиция такова, что это имеет право быть. Ибо в самой VCL:


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


Шо ничто иное как вызов деструктора внутри метода объекта.
Я подозреваю, что где-то в хелпе об этом написано. Однако есть у кого коротко и по делу?


 
StriderMan   (2009-08-03 18:38) [1]

да нормальное поведение.

вот более подходящий пример из VCL

function TInterfacedObject._Release: Integer;
begin
 Result := InterlockedDecrement(FRefCount);
 if Result = 0 then
   Destroy;
end;


 
Dimka Maslov ©   (2009-08-03 18:40) [2]

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


 
Palladin ©   (2009-08-03 18:42) [3]


>  [2] Dimka Maslov ©   (03.08.09 18:40)

Это минус и деструктора тоже. И Free.


 
Dimka Maslov ©   (2009-08-03 18:45) [4]


> Palladin ©   (03.08.09 18:42) [3]


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


 
Palladin ©   (2009-08-03 18:47) [5]

Хм, не вижу связи между инициатором уничтожения и вызовом деструктора из метода.


 
Dimka Maslov ©   (2009-08-03 18:48) [6]

А она есть :))


 
Palladin ©   (2009-08-03 18:49) [7]

Это тебе не суслик. Следуя твоей логике метод Free тоже нужно искоренить. Потому что "желательно, чтобы объект уничтожал тот, кто его создал".


 
StriderMan   (2009-08-03 18:49) [8]


> Вот поэтому желательно, чтобы объект уничтожал тот, кто его создал.

VCL явно не придерживается такой концепции.
Вот примеры:
1. Сабж.
2. TComponent.Create(Owner) - Owner разрушит
3. TControl.Parent := - Parent тоже попытается разрушить
4. TThread.FreeOnTerminate


 
pasha_golub ©   (2009-08-03 18:50) [9]


> А она есть :))

Это про суслика!


> Dimka Maslov ©   (03.08.09 18:40) [2]
>
> Минус такого подхода в том, что вызывающая процедура (при
> наличии таковой) не будет знать, что объект уже уничтожен
> и при повторной попытке уничтожить объект произойдет AV.
>

А сделать нечто подобное FreeAndNill возможно изнутре? Там где неонка...


 
Palladin ©   (2009-08-03 18:51) [10]


> А сделать нечто подобное FreeAndNill возможно изнутре?

Нет. Сколько раз уже эта тема обсасывалась... )


 
Dimka Maslov ©   (2009-08-03 18:52) [11]

Хорошо, переформулируем фразу так:
"желательно, чтобы деструктор объекта вызывался процедурой(объектом), в которой был вызван его конструктор".


 
Dimka Maslov ©   (2009-08-03 18:58) [12]


> VCL явно не придерживается такой концепции.

Пускай не придерживается. Это вопрос личных предпочтений. Уверен в себе - можешь поступать как хочешь.


> А сделать нечто подобное FreeAndNill возможно изнутре?

Только если в самом объекте держать список всех ссылок на сам объект. Явно нереально.


 
StriderMan   (2009-08-03 18:58) [13]


> Хорошо, переформулируем фразу так:
> "желательно, чтобы деструктор объекта вызывался процедурой(объектом),
>  в которой был вызван его конструктор".

Да как ни переформулируй, в VCL этот принцип не выполняется.

Я абсолютно согласен, что гораздо надежнее самостоятельно контролировать где и что разрушается, однако коль скоро VCL этого не придерживается, программистам приходится подстраиваться под нее


 
StriderMan   (2009-08-03 19:00) [14]


> Пускай не придерживается. Это вопрос личных предпочтений. Уверен в себе - можешь поступать как хочешь.

VCL это не вопрос личных предпочтений, а основа почти всех проектов на Делфи. Хочешь не хочешь а она есть


 
Palladin ©   (2009-08-03 19:00) [15]


> [13] StriderMan   (03.08.09 18:58)

ты не путай теплое с мягким... когда ты создаешь компонент выполняется его агрегация во владельца(родителя) и он вправе его освобождать... это никак не противоречит ООП...


 
Юрий Зотов ©   (2009-08-03 19:02) [16]

> pasha_golub ©   (03.08.09 18:36)

Ничего не подозревая о засаде, вызываем метод SomeProc из другой процедуры, в которой после вызова SomeProc есть прямое или опосредованное обращение к полям объекта.

Все вполне законно - а получаем AV. И чешем репу в непонятках. Кто ж мог знать, что разработчик класса так изгальнулся?

Дурной это тон, Паша, когда объект сам себя убивает. Опасно. А интерфейсы - это совсем другое дело, там счетчик ссылок безопасность обеспечивает.


 
StriderMan   (2009-08-03 19:03) [17]


> это никак не противоречит ООП...

а я и не говорю что, противоречит. Как и сабж


 
Palladin ©   (2009-08-03 19:09) [18]


> [17] StriderMan   (03.08.09 19:03)

А так же и не противоречит и докторине "ручного" особождения объектов. Нет ничего зазорного в том, что объекты в составе TObjectList освобождаются. Это никак не противоречит "я тебя породил я тебя и убью".


 
Юрий Зотов ©   (2009-08-03 19:09) [19]

> StriderMan   (03.08.09 18:49) [8]

> Owner разрушит
> Parent тоже попытается разрушить

Не-а, не попытается. При разрушении объект автоматически исключается из списка Controls.

Из списка Components, кстати, тоже - так что если Parent объект убил, то Owner об этом объекте уже ничего не знает, он уже вообще не Owner.


 
Dimka Maslov ©   (2009-08-03 19:09) [20]


> StriderMan   (03.08.09 18:58) [13]


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


> StriderMan   (03.08.09 19:00) [14]

Другими словами, надо уничтожать объекты где попало, а потом бороться с AV и утечками памяти? Нет. Надо осознанно подходить к данному вопросу. И пользоваться тем способом, который предпочтительнее в данной конкретной ситуации. Что же касается VCL — основы почти всех проектов на Делфи, она, при желании и за исключением особо тонких мест, поддаётся обработке напильником.


 
StriderMan   (2009-08-03 19:09) [21]


>  А интерфейсы - это совсем другое дело, там счетчик ссылок безопасность обеспечивает.

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


 
StriderMan   (2009-08-03 19:11) [22]


> Другими словами, надо уничтожать объекты где попало, а потом бороться с AV и утечками памяти?

нет. Этим надо пользоваться осторожно

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

так а что мешает программисту использовать такой подход, если он уверен что никто другой... ?


 
Palladin ©   (2009-08-03 19:12) [23]


> [21] StriderMan   (03.08.09 19:09)

Смешаный режим работы с наследниками TInterfacedObject сам по себе абсолютно не привествуется. И это будет ошибкой того самого программиста.


 
Dimka Maslov ©   (2009-08-03 19:14) [24]


> так а что мешает программисту использовать такой подход,
>  если он уверен что никто другой... ?


Ничего не мешает. Буквально вообще ничего.


 
StriderMan   (2009-08-03 19:15) [25]


> Смешаный режим работы с наследниками TInterfacedObject сам по себе абсолютно не привествуется. И это будет ошибкой того самого программиста.

перекрываем _AddRef и _Release >> вуаля! Всё безопасно!


 
Mystic ©   (2009-08-03 19:18) [26]

Да, такая ситуация, как описана в сабже, возможна. Но требует более тщательного проектирования времени жизни объектов.


> А сделать нечто подобное FreeAndNill возможно изнутре? Там
> где неонка...


Это называется weak references (слабые ссылки). Стандартного такого механизма в Delphi нет. Тут есть описание С++ механизма, который можно перенести на Delphi

http://www.sources.ru/wiki/doku.php?id=doc:cpp:boost:shared_ptr


 
jack128_   (2009-08-03 19:54) [27]


> Смешаный режим работы с наследниками TInterfacedObject сам
> по себе абсолютно не привествуется. И это будет ошибкой
> того самого программиста.

ну сами разрабы дельфи написали такой ужос, как TXMLDocument...


 
pasha_golub ©   (2009-08-03 20:04) [28]


> Нет. Сколько раз уже эта тема обсасывалась... )

Я не обсасывал... Не успел.


 
pasha_golub ©   (2009-08-03 20:05) [29]


> StriderMan   (03.08.09 19:09) [21]
>
>
> >  А интерфейсы - это совсем другое дело, там счетчик ссылок
> безопасность обеспечивает.
>
> Вот только если программист не знал что класс этот реализует
> некие интерфейсы, а где-то в недрах чужого кода некая интерфейсная
> переменная внезапно получила ссылку на этот объект и разрушила
> его. Программист опять же получит AV.

+100

Убил бы. Нарвался на сью граблю. Чуть моск не поломал


 
pasha_golub ©   (2009-08-03 20:07) [30]


> Palladin ©   (03.08.09 19:12) [23]
>
>
> > [21] StriderMan   (03.08.09 19:09)
>
> Смешаный режим работы с наследниками TInterfacedObject сам
> по себе абсолютно не привествуется. И это будет ошибкой
> того самого программиста.

Однако в мануале рекоммендуется использовать TInterfacedObject как прародителя, тудытегоразтудыт...


 
pasha_golub ©   (2009-08-03 20:08) [31]


> jack128_   (03.08.09 19:54) [27]
> ну сами разрабы дельфи написали такой ужос, как TXMLDocument.
> ..

Жень, поподробней могешь для аутсайдеров?


 
oxffff ©   (2009-08-03 21:19) [32]


> Mystic ©   (03.08.09 19:18) [26]
> Да, такая ситуация, как описана в сабже, возможна. Но требует
> более тщательного проектирования времени жизни объектов.
>  
>
>
> > А сделать нечто подобное FreeAndNill возможно изнутре?
>  Там
> > где неонка...
>
>
> Это называется weak references (слабые ссылки). Стандартного
> такого механизма в Delphi нет. Тут есть описание С++ механизма,
>  который можно перенести на Delphi


Слабая ссылка в delphi делается элементарно.


 
тимохов ©   (2009-08-03 22:44) [33]


> oxffff ©   (03.08.09 21:19) [32]
> Слабая ссылка в delphi делается элементарно.


нет, ты не прав.


 
Юрий Зотов ©   (2009-08-03 22:49) [34]

> тимохов ©   (03.08.09 22:44) [33]

+5 :0)


 
jack128_   (2009-08-03 22:59) [35]


>
> Жень, поподробней могешь для аутсайдеров?

TXMLDocument ведет подсчет ссылок, если ему в конструктор передали nil,  иначе ведет ся как компонент. В ОЧумелых руках страшная вещь может получиться.


 
тимохов ©   (2009-08-03 23:00) [36]


> Юрий Зотов ©   (03.08.09 22:49) [34]
>
> > тимохов ©   (03.08.09 22:44) [33]
>
> +5 :0)


Мне тоже понравилось. Главное - как я точно сказал! А какая аргументация!!! Все бы так объяснялись.

))


 
Дмитрий С ©   (2009-08-04 07:26) [37]


> тимохов ©   (03.08.09 23:00) [36]

Элементарно не значит просто. Поэтому...


 
oxffff ©   (2009-08-04 08:30) [38]


> тимохов ©   (03.08.09 22:44) [33]
>
> > oxffff ©   (03.08.09 21:19) [32]
> > Слабая ссылка в delphi делается элементарно.
>
>
> нет, ты не прав.


Приветствую, Дмитрий.

1. WeakRefStuff=Pointer(Iunknown).

2. class=class(TinterfacedObject,WeakInterface)

 function WeakInterface._Addref=WeakAddref
 function WeakInterface._Release=WeakRelease

 function WeakAddref
 function  WeakRelease

3. Делегация реализации аггрегированному объекту с указанием семантики копирования.

4. Динамическое создание интерфейса.

5. И др.

6. Использование GC в native delphi

http://cc.embarcadero.com/Item/21646
http://cc.embarcadero.com/Item/26716

Теперь жду от тебя не меньшей аргументации.


 
brother ©   (2009-08-04 08:35) [39]

> Теперь жду от тебя не меньшей аргументации.


> 5. И др.

убойный аргумент ;)


 
oxffff ©   (2009-08-04 08:36) [40]


> brother ©   (04.08.09 08:35) [39]


ГЫ ГЫ.


 
Palladin ©   (2009-08-04 08:59) [41]


> [30] pasha_golub ©   (03.08.09 20:07)

Речь идет об использовании инстанцированных экземпляров поддерживающих интерфейсы. То есть либо ты уж с ними как с объектами работай, либо как с инетрфейсам, а иначе как написал jack128_ - катаклизм наступить может.


 
Palladin ©   (2009-08-04 09:20) [42]

вот кстати простейший примерчик катаклизма

Procedure lw(Const s:String);
Begin
Form1.Memo1.Lines.Add(s);
End;

Type
IMyIfc=Interface
 Procedure p1;
End;

TMyIfc=Class(TInterfacedObject,IMyIfc)
 Public
  Constructor Create;
  Destructor Destroy; Override;
  Procedure p1;
End;

Constructor TMyIfc.Create;
Begin
lw("TMyIfc.Create");
End;

Destructor TMyIfc.Destroy;
Begin
lw("TMyIfc.Destroy");
End;

Procedure TMyIfc.p1;
Begin
lw("TMyIfc.p1");
End;

Procedure pp(i:IMyIfc);
Begin
i.p1;
End;

procedure TForm1.Button1Click(Sender: TObject);
Var
o:TMyIfc;
begin
o:=TMyIfc.Create;
lw("call pp");
pp(o);
lw("direct");
o.p1;
o.Free;
end;


 
Юрий Зотов ©   (2009-08-04 09:35) [43]

> Palladin ©   (04.08.09 08:59) [41]

А самое чудное, что вину за этот катаклизм почему-то вешают на VCL, хотя как раз в данном случае кривизна рук более чем очевидна.


 
Ega23 ©   (2009-08-04 09:45) [44]


> > jack128_   (03.08.09 19:54) [27]
> > ну сами разрабы дельфи написали такой ужос, как TXMLDocument.
>
> > ..
>
> Жень, поподробней могешь для аутсайдеров?


Месяца 3 назад у меня было. Убил пол-дня. Чуть не выломал себе мозг. Ну неправильно себя ведёт - и точка.
Как раз Женя и нашёл баг свежим взглядом - я вместо
var
 doc : IXMLDocument
объявил
var
 doc : TXMLDocument


 
brother ©   (2009-08-04 09:47) [45]

> var
> doc : IXMLDocument
> объявил
> var
> doc : TXMLDocument

жестко(


 
Ega23 ©   (2009-08-04 09:50) [46]


> жестко(


Фигли жёстко? Читаю хелп, там сказано, что в случае передачи в конструктор валидного Owner-а эта хрень ведёт себя как обычный VCL-компонент (а-ля TOpenDialog или TDataSource).
В случае передачи туда nil  - как TInterfacedObject с подсчётом ссылок.


 
brother ©   (2009-08-04 10:38) [47]

> Фигли жёстко?

я про опечатку, трудно обнаружить... человеческий фактор епт...


 
Тимохов_   (2009-08-04 10:41) [48]


> oxffff ©   (04.08.09 08:30) [38]
> Теперь жду от тебя не меньшей аргументации.


Сергей, то была шутка: пародия на твою манеру лаконичного общения ))
Ну я думаю ты понял. А вот то, что ты дал наконец аргументированный ответ о том, как ты сделал бы weakref - это очень хорошо. :)


 
pasha_golub ©   (2009-08-04 10:53) [49]


> Ega23 ©   (04.08.09 09:45) [44]


> Месяца 3 назад у меня было. Убил пол-дня.

У меня тоже. Но как раз я накосячил. Однако ж замыленному глазу найти что-то очень трудно.


 
Anatoly Podgoretsky ©   (2009-08-04 11:27) [50]

> pasha_golub  (04.08.2009 10:53:49)  [49]

I и T очень похожb в Courier New


 
brother ©   (2009-08-04 11:28) [51]

> I и T очень похожb в Courier New

подтверждаю


 
brother ©   (2009-08-04 11:37) [52]

те. подтверждаю )


 
StriderMan   (2009-08-04 12:10) [53]

а че-то про TThread.FreeOnTerminate забыли? Тоже дурным тоном считается в широких кругах.


 
pasha_golub ©   (2009-08-04 18:31) [54]


> StriderMan   (04.08.09 12:10) [53]
>
> а че-то про TThread.FreeOnTerminate забыли? Тоже дурным
> тоном считается в широких кругах.

Если человек себе сама злобная деревяшка, то он где угодно граблю найдет. Я, например, на копи-пасте нарывался несколько раз. :)) Ну, что поделать, если у этого ДевЭкса такие длинные проперти и методы, млин.



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

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

Наверх




Память: 0.61 MB
Время: 0.018 c
2-1248705880
xyz
2009-07-27 18:44
2009.10.04
listbox не ловит нажатие Del


2-1248969500
ford
2009-07-30 19:58
2009.10.04
Delimiter и QuoteChar


15-1247390113
Sergey Masloff
2009-07-12 13:15
2009.10.04
Эх, прокачу Москва-Воронеж-Ростов-(Ейск)


2-1248680807
ford
2009-07-27 11:46
2009.10.04
TWordApplication выдает ошибку - "вызов был отклонен"


15-1249370873
Kerk
2009-08-04 11:27
2009.10.04
Набор "Юный либерал"