Форум: "Начинающим";
Текущий архив: 2007.11.11;
Скачать: [xml.tar.bz2];
ВнизКак убить объект из его же метода? Найти похожие ветки
← →
oxffff © (2007-10-12 15:26) [40]Можно убивать по разному, главное чтобы убить. А как это без разницы.
← →
Ins © (2007-10-12 15:31) [41]Даже PostMessage самому себе (как сделано в Release) тоже не так чист как кажется с той точки зрения, что обработчик сообщения вызывается из другого метода (Dispatch что-ли), а тот - из WndProc. Если ничего не путаю, точнее нужно глянуть исходники. Так вот, вызывая Free в обработчике CM_Release - мы полностью доверяем Борланду, что после вызова этого обработчика и возврата в Dispatch и WndProc не будет никакого обращения к Self. Так что делая так, скрестите пальцы и молитесь-молитесь... :) Хотя на самом деле не будет, Борланд об этом позаботился.
← →
oxffff © (2007-10-12 15:32) [42]
> Ins © (12.10.07 15:20) [39]
>
> > palva © (12.10.07 15:12) [37]
>
> Просто можно сделать безопасно. Сделав это не из метода
> своего класса. Иначе - небезопасно, так как метод продолжает
> выполняться с невалидным self. Повезет-неповезет, зависит
> от того, как это реализует программист. Задумается ли он
> о многих не очень очевидных вещах (в частности, что не только
> к полям нельзя обращаться, но и к виртуальным методам).
> И от того, откуда этот метод вызван. Если из другого метода,
> то теперь ответственность на том другом методе.
Если слегка подумать и подмутить, то можно сделать так, что после вызова Free можно у объекта вызывать методы, в том числе и виртуальные и обращаться к полям. :)
Все в твоих руках. Это так к сведению
← →
Игорь Шевченко © (2007-10-12 15:35) [43]на С# надо писать. Там мусор собирается. Сам.
← →
Ins © (2007-10-12 15:37) [44]
> oxffff © (12.10.07 15:32) [42]
Практика показывает, что на эти грабли периодически наступают. Именно из-за непонимания того, что после вызова Free метод представляет собой некий чемоданчик с проводками, из которого раздается тик-так. Не верите мне - верьте статистике :)
← →
Игорь Шевченко © (2007-10-12 15:38) [45]Ins © (12.10.07 15:37) [44]
Практика показывает, что наступают абсолютно на все грабли, на которые только можно наступить, и по несколько раз :)
← →
oxffff © (2007-10-12 15:38) [46]
> Игорь Шевченко © (12.10.07 15:35) [43]
> на С# надо писать. Там мусор собирается. Сам.
Неа. Tobject надо знать. ;)
Перекрываем FreeInstance оставляем Cleanup.
И добавляет добавление в очередь на удаление из кучи, которую (очередь) можно проверять в отдельном потоке. Вот вам почти .NET.
← →
Ins © (2007-10-12 15:39) [47]
> Ins © (12.10.07 15:37) [44]
А все из-за того, что обращение к self иногда идет неявно. Как с теми же виртуальными методами. Потом очень долго ищут ошибку.
← →
oxffff © (2007-10-12 15:40) [48]
> oxffff © (12.10.07 15:38) [46]
>
> > Игорь Шевченко © (12.10.07 15:35) [43]
> > на С# надо писать. Там мусор собирается. Сам.
>
>
> Неа. Tobject надо знать. ;)
> Перекрываем FreeInstance оставляем Cleanup.
> И добавляет добавление в очередь на удаление из кучи, которую
> (очередь) можно проверять в отдельном потоке. Вот вам почти
> .NET.
Каким образом до очередной сборки мусора, Обращение к объекту или виртуальному методу во всяком случае не вызовет ошибку.
← →
Игорь Шевченко © (2007-10-12 15:42) [49]oxffff © (12.10.07 15:38) [46]
При всем уважении не могу согласиться :) Чем-то мне это напоминает реактор на субтепловых нейтронах и шины из полиаминного нестирающегося волокна.
← →
oxffff © (2007-10-12 15:43) [50]procedure TXObject.FreeInstance;
begin
CleanupInstance;
PendingQueue.insert(self);
end;
procedure KillAllPendingObject;
begin
//проходим по очереди и вызывает Free для каждого элемента
end;
← →
oxffff © (2007-10-12 15:46) [51]
> Игорь Шевченко © (12.10.07 15:42) [49]
> oxffff © (12.10.07 15:38) [46]
>
> При всем уважении не могу согласиться :) Чем-то мне это
> напоминает реактор на субтепловых нейтронах и шины из полиаминного
> нестирающегося волокна.
Вы знаете делать можно по разному. Главное чтобы работало.
За это я очень ценю гибкость Delphi.
← →
oxffff © (2007-10-12 15:47) [52]
> procedure KillAllPendingObject;
> begin
> //проходим по очереди и вызывает Free для каждого элемента
> end;
Freemem естественно.
← →
Сергей М. © (2007-10-12 15:49) [53]
> я очень ценю гибкость Delphi
Оную твою "любовь" и видно по твоим постам)
← →
oxffff © (2007-10-12 15:52) [54]
> Сергей М. © (12.10.07 15:49) [53]
>
> > я очень ценю гибкость Delphi
>
>
> Оную твою "любовь" и видно по твоим постам)
День добрый Сергей М. :)
← →
palva © (2007-10-12 16:23) [55]
> > я очень ценю гибкость Delphi
> Оную твою "любовь" и видно по твоим постам)
А он и не говорил, что любит. Говорил что ценит.
Ценить - это любить за деньги.
← →
Leonid Troyanovsky © (2007-10-12 18:18) [56]
> Игорь Шевченко © (12.10.07 15:10) [36]
type
EFreeObject = class(EAbort)
private
FObject : TObject;
public
property AObject: TObject read FObject;
constructor CreateFO(AObject: TObject); virtual;
destructor Destroy; override;
end;
constructor EFreeObject.CreateFO(AObject: TObject);
begin
inherited CreateFmt("Object %p, classname %s", [Pointer(AObject), AObject.ClassName]);
FObject := AObject;
end;
destructor EFreeObject.Destroy;
begin
if (FObject = Application) or
(FObject = Application.MainForm) then
Application.Terminate
else
FObject.Free;
inherited;
end;
procedure FreeObject(AObject: TObject);
begin
raise EFreeObject.CreateFO(AObject);
end;
Тестировалось по-пятничному :)
--
Regards, LVT.
← →
oxffff © (2007-10-12 22:32) [57]
> Leonid Troyanovsky © (12.10.07 18:18) [56]
> Тестировалось по-пятничному :)
Я если исключение не дойдет до Application.HandleException(Self)?
Извольте получить AV
procedure TForm1.Button1Click(Sender: TObject);
var A:Tobject;
begin
a:=Tobject.Create;
try
FreeObject(a);
except
end;
showmessage(a.ClassName);
end;
Пример упрощен.
Так что и в этом случае гарантии попаданения в почти в "top caller", т.е MainWndProc нет.
← →
Leonid Troyanovsky © (2007-10-13 10:17) [58]
> oxffff © (12.10.07 22:32) [57]
> Так что и в этом случае гарантии попаданения в почти в "top
> caller",
Ну, я надеюсь, что уважаемый Ega23 не будет в локальных
обработчиках гасить EAbort.
А чтобы не вводить никого в заблуждение откажемся от FreeObject
и будем звать непоср-но raise EFreeObject.CreateFO(AObject).
--
Regards, LVT.
← →
Сусл © (2007-10-13 11:44) [59]а в чем проблема убить?
берешь и убиваешь.
tobject.free посмотри
← →
Leonid Troyanovsky © (2007-10-13 12:31) [60]
> Сусл © (13.10.07 11:44) [59]
> tobject.free посмотри
Посмотри остальные 57 сообщений.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2007-10-15 14:06) [61]
> Leonid Troyanovsky © (13.10.07 10:17) [58]
> А чтобы не вводить никого в заблуждение откажемся от FreeObject
> и будем звать непоср-но raise EFreeObject.CreateFO(AObject).
Продвигаемся еще дальше и откажемся от автоматического
разрушения объекта после обработки исключения.
Т.е., если некий объект не может больше работать, то он
должен возбудить исключение (необязательно класса EAbort),
для информирования об этом обстоятельсве того, кто вызвал
метод этого объекта, а уж в обработчике исключений этого
уровня принимать решение о дальнейшей судьбе объекта.
В любом случае, удерживаемая на этом уровне ссылка
на объект может быть обнулена вовремя.
--
Regards, LVT.
← →
Игорь Шевченко © (2007-10-15 15:29) [62]Leonid Troyanovsky © (15.10.07 14:06) [61]
> Т.е., если некий объект не может больше работать, то он
>
> должен возбудить исключение (необязательно класса EAbort),
>
> для информирования об этом обстоятельсве того, кто вызвал
>
> метод этого объекта, а уж в обработчике исключений этого
>
> уровня принимать решение о дальнейшей судьбе объекта.
Это я понимаю, выпрямители там, тумбы разные, это нам товарищ ВрИО довольно хорошо объяснил. Но вот один момент до конца не понятен - а нафига, собственно, нужны действия в отквоченном тексте ?
← →
Leonid Troyanovsky © (2007-10-15 15:40) [63]
> Игорь Шевченко © (15.10.07 15:29) [62]
> а нафига, собственно, нужны действия в отквоченном тексте ?
Как мне представляется, это и есть ответ на вопрос из subject.
Т.е. (безопасно) уничтожить объект из его же метода нельзя.
Если желание, все же, не проходит, то действовать надо
в направлении [61].
--
Regards, LVT.
← →
Игорь Шевченко © (2007-10-15 15:46) [64]Leonid Troyanovsky © (15.10.07 15:40) [63]
> Т.е. (безопасно) уничтожить объект из его же метода нельзя.
>
> Если желание, все же, не проходит, то действовать надо
> в направлении [61].
Можно уничтожить. Если потом не обращаться к уничтоженному объекту :)
Отсюда, собственно и вопрос [62]
← →
Ins © (2007-10-15 15:49) [65]
> Игорь Шевченко © (15.10.07 15:46) [64]
Мне тут недавно Юрий Зотов объяснял, что переходить дорогу не на переходе тоже можно. И курить на бочке с порохом тоже ;-) По-моему случай из той же оперы...
← →
Leonid Troyanovsky © (2007-10-15 15:51) [66]
> Игорь Шевченко © (15.10.07 15:46) [64]
> Можно уничтожить. Если потом не обращаться к уничтоженному
> объекту :)
Мне не нравится "если". Умерла - так умерла.
Если добавить, например, к Release честное описание всех
условий (ограничений) ее применения, то применять ее не будут.
Хотя, и сама нужда в примение подобных вещей подозрительна :)
--
Regards, LVT.
← →
Игорь Шевченко © (2007-10-15 15:59) [67]Leonid Troyanovsky © (15.10.07 15:51) [66]
Если (уж извини!) ты в методе другого объекта обратишься к уничтоженному, то получишь тоже массу неприятных эффектов :)
Не следует ли из этого, что уничтожение объектов надо запретить вообще ?
Или я чего-то здорово не понимаю ? :)
← →
Leonid Troyanovsky © (2007-10-15 16:12) [68]
> Игорь Шевченко © (15.10.07 15:59) [67]
> Или я чего-то здорово не понимаю ? :)
Ты снова подозреваешь меня в:
foo.Free;
foo.Smthng; :)
А я про неявное уничтожение.
Т.е., мы делаем:
foo.Smthng;
foo.Smthng2; // а в предыдущем вызове произошел суицид
Кроме того, мне не нравится, что после вызова "терминатора"
может происходить еще что-то неочевидное.
--
Regards, LVT.
← →
Игорь Шевченко © (2007-10-15 16:27) [69]Leonid Troyanovsky © (15.10.07 16:12) [68]
> Кроме того, мне не нравится, что после вызова "терминатора"
> может происходить еще что-то неочевидное.
Например, что ?
> А я про неявное уничтожение.
> Т.е., мы делаем:
> foo.Smthng;
> foo.Smthng2; // а в предыдущем вызове произошел суицид
Я с чем могу согласиться - что суицид объекта не самый ясный из примеров кода сам по себе. Читаешь код, видишь суицид, впадаешь в краткий ступор. С этим согласен и не спорю, лучше объект убивать принудительно извне - по крайней мере, читабельно.
Но городить дополнительный огород, чтобы все-таки разрешать суицид, и, как следствие, неочевидный код - тут я впаду в еще больший ступор.
Так как я считаю, чем меньше ступора, тем лучше, то и задал вопрос [62] - а нафига ? :)
← →
Суслик (2007-10-15 17:07) [70]
> [60] Leonid Troyanovsky © (13.10.07 12:31)
> > Сусл © (13.10.07 11:44) [59]
> > tobject.free посмотри
> Посмотри остальные 57 сообщений.
Осилил, ух...
Ну что сказать - разговор очень ни о чем, ибо знать надо контекст задачи лучше, чем это раскрыто в тексте топика.
Убиение себя - вещь неординарная. У меня в моем OPF фреймворке есть несколько таких моментов. Но каждый из них продокументирован жесточайщим образом с акцентами на тонкостях жизни после смерти.
Посему мое имхо - убивать себя объекту плохо, но если нужно, то почему нет? Free для этого вполне подходит.
ЗЫ Перечитал - ни о чем написал. Ну так и топик вобщем-то не особо информативен :)
← →
Leonid Troyanovsky © (2007-10-15 17:49) [71]
> Игорь Шевченко © (15.10.07 16:27) [69]
> > Кроме того, мне не нравится, что после вызова "терминатора"
> > может происходить еще что-то неочевидное.
> Например, что ?
Например, если после вызова Free произойдет _неявный_
вызов еще чего-либо и в, конечном счете, к обращению
к уже несуществующему объекту.
Ну, не можем мы гарантировать, что вызов Free - последнее,
что выполняется в методе. Например, Release & ProcessMessages.
> Но городить дополнительный огород, чтобы все-таки разрешать
> суицид, и, как следствие, неочевидный код - тут я впаду
> в еще больший ступор.
А я его и не разрешал, более того, никак не оправдывал.
Все, что я предложил в [61] - достаточно академично:
try
foo.smthng; // при вызове метода объект может стать негоден к жизни
except
on E: EFreeObject do
begin
foo.Free;
raise; // дальнейшее выполнение кода с foo не имеет смысла
end;
end;
Или освобождать foo в секции finally.
Вот, собс-но.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2007-10-15 18:03) [72]
> Суслик (15.10.07 17:07) [70]
> Убиение себя - вещь неординарная. У меня в моем OPF фреймворке
> есть несколько таких моментов. Но каждый из них продокументирован
> жесточайщим образом с акцентами на тонкостях жизни после
> смерти.
Ну, а стоит ли делать столько оговорок, типа: после этого
вызова нельзя делать то-то и то-то, а это предварять этим.
Нам должно быть достаточно знать, что конструктор создает,
а Destroy - убивает, никакие компромиссы вроде функций,
возвращающих объект или методов-убийц нам не нужны.
А если при выполнении метода что-то пошло не так, то
исключение - вполне достойный способ известить об этом.
> ЗЫ Перечитал - ни о чем написал. Ну так и топик вобщем-то
> не особо информативен :)
Может и так.
Однако, мне удалось, надеюсь, избавиться от некоторых
заблуждений на эту тему.
--
Regards, LVT.
← →
Palladin © (2007-10-15 18:07) [73]ну, млин, из-за такой ерунды такую страшную дилему развели... реально, ИМХО, если вдруг объекту требуется самое себя уничтожить, то это уже ошибка проектирования...
← →
Leonid Troyanovsky © (2007-10-15 18:23) [74]
> Palladin © (15.10.07 18:07) [73]
> .. реально, ИМХО, если вдруг объекту требуется самое себя
> уничтожить, то это уже ошибка проектирования...
Уже два ИМХО :)
Но, к сожалению (?), такие вещи голосованием не решают.
А самые длиные топики растут из ерунды, вроде
PChar & String, global variable - MD, формы в dll & etc :)
--
Regards, LVT.
← →
oxffff © (2007-10-15 19:16) [75]
> Palladin © (15.10.07 18:07) [73]
> ну, млин, из-за такой ерунды такую страшную дилему развели.
> .. реально, ИМХО, если вдруг объекту требуется самое себя
> уничтожить, то это уже ошибка проектирования...
Странно, вообще все объекты себя сами убивают. См. destroy
Речь видимо шла об управлением временем жизни объекта?
← →
Ins © (2007-10-15 19:19) [76]
> Например, Release & ProcessMessages.
Вот менее очевидный пример:unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
protected
procedure WndProc(var Message: TMessage); override;
procedure WtiteToLog(Message: TMessage); virtual;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Release;
end;
procedure TForm1.WndProc(var Message: TMessage);
begin
inherited;
WtiteToLog(Message);
end;
procedure TForm1.WtiteToLog(Message: TMessage);
begin
// Do something
end;
end.
← →
Leonid Troyanovsky © (2007-10-15 19:21) [77]
> oxffff © (15.10.07 19:16) [75]
> Речь видимо шла об управлением временем жизни объекта?
Видимо, речь шла о том, что видимо.
Убиение объекта из его же метода, см. сабж.
Вот, поэтому, IMHO, и обсуждения простых вещей столь длительны.
Потому, как каждый позволяет себе вольность восприятия темы
и ее предыдущих обсуждений.
--
Regards, LVT.
← →
oxffff © (2007-10-15 19:28) [78]
> Видимо, речь шла о том, что видимо.
> Убиение объекта из его же метода, см. сабж.
Тогда каждый объект убивает себя сам.
Destroy, FreeInstance чьи методы? :)
← →
oxffff © (2007-10-15 19:29) [79]
> Leonid Troyanovsky © (15.10.07 19:21) [77]
Возможно ли с вами как то связаться?
Страницы: 1 2 3 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.11.11;
Скачать: [xml.tar.bz2];
Память: 0.63 MB
Время: 0.067 c