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

Вниз

Метод   Найти похожие ветки 

 
VetMIg   (2002-05-08 14:45) [0]

Почему, когда я уничтожаю форму методом "Free". После 3-го закрытия этой формы программа выдает ошибку?
Пример:
...
Form1.Visible:= False;
Form1.Free;
...


 
Кулюкин Олег   (2002-05-08 14:50) [1]

Не зная какую ошибку выдает программа, ответить крайне трудно.
Скорее всего, ошибка в 17-й строке :))


 
Val   (2002-05-08 14:51) [2]

страшная строчка :О


 
Alx2   (2002-05-08 15:01) [3]

Попробуй вместо метода Free процедуру FreeAndNil


 
Johnny Smith   (2002-05-08 16:05) [4]

А ошибка-то какая?


 
Romkin   (2002-05-08 16:17) [5]

Потому, что форму надо закрывать не вызовом Free, а вызовом Release. А ошибка должна быть AV


 
Val   (2002-05-08 16:34) [6]

>Romkin © (08.05.02 16:17)
почему же не Free, а Release?


 
Romkin   (2002-05-08 16:40) [7]

См. Help на Release
Дело в том, что у формы есть очередь сообщений, и при вызове Free она может быть не пустой. Результат - форма уничтожена вместе с handle окна, а потом приложение доходит до обработки сообщений, и отправляет сообщения уничтоженному handle.
При этом возникает access violation, причем не сразу и в разных местах - фиг оттрассируешь


 
Внук   (2002-05-08 16:44) [8]

>>Romkin © (08.05.02 16:40)
Теоретически Вы правы, конечно, но практически это большая редкость. Более того, открою страшную тайну - не разу в своей жизни не использовал TForm.Release - и ничего :)


 
Val   (2002-05-08 16:45) [9]

ну тогда уж вместе почитаем:
..Any event handlers of the form should use Release..
это нам где же сказано, откуда автор вопроса форму уничтожает, чтобы Release использовать?


 
Внук   (2002-05-08 16:46) [10]

Упс... Правильно писать - НИ разу не использовал ...


 
Romkin   (2002-05-08 16:53) [11]

Повезло. Зависит от многих факторов, у меня были такие классические AV, программист написал везде Free, и два часа ловил ошибку :-))


 
kull   (2002-05-08 18:32) [12]


> Romkin ©

Почему Release а не Close?

Мастера, мастера ...


 
Malder   (2002-05-08 18:59) [13]

Лично я не понял вопроса. "После 3-го закрытия этой формы программа выдает ошибку?" - ахинея какая-то. Что значит "После 3-го закрытия формы " ? После того, как три раза вызывал метод Free ?! Да после же первого Form1.Free любое обращение к форме будет вызывать ошибку...


 
paul_shmakov   (2002-05-08 20:25) [14]

Romkin прав и нечего здесь спорить. Читайте хелп внимательно:

Destroys the form and frees its associated memory.

procedure Release;

Description

Use Release to destroy the form and free its associated memory.

Release does not destroy the form until all event handlers of the form and event handlers of components on the form have finished executing. Any event handlers of the form should use Release. Failing to do so could lead to an access violation.


ну а то, что у кого-то и Free нормально работает, так может и FreeMem какой-нибудь тоже нормально работать будет... некоторое время.


 
VetMIg   (2002-05-14 14:25) [15]

Классно конечно, но вот я увидел вопрос: Что значит "После 3-го закрытия формы"? . Так вот... Первые два раза форма закрывается нормально и не выдает никаких ошибок. А на третий раз выводит ошибку.


 
Andrey007   (2002-05-14 15:02) [16]

if Form1<>nil then FreeAndNil(Form1);

FreeAndNil procedure

Frees an object reference and replaces the reference with nil.

procedure FreeAndNil(var Obj);

Description

Use FreeAndNil to ensure that a variable is nil after you free the object it references. Pass any variable that represents an object as the Obj parameter.

Warning: Do not pass a value for Obj if it is not an instance of TObject or one of its descendants.


 
kull   (2002-05-14 15:06) [17]


> paul_shmakov © (08.05.02 20:25)
> Romkin прав и нечего здесь спорить. Читайте хелп внимательно:

А примечание к этому help-у тоже внимательно читали?

Note: Release returns immediately to the caller. It does not wait for the form to be freed before returning.

А вот Close ждет пока закроется.


 
NailS   (2002-05-14 15:10) [18]

Повторяясь за Кулюкин Олег, Johnny Smith, все таки решусь спросить

КАКУЮ ОШИБКУ ВЫДАЕТ ПРОГРАММА ПРИ ЗАКРЫТИИ ФОРМЫ?

и где находятся строчки кода

Form1.Visible:= False;
Form1.Free;



 
Внук   (2002-05-14 15:17) [19]

Пока не будет кода, не будет и толькового ответа, IMHO.


 
Anatoly Podgoretsky   (2002-05-14 15:23) [20]

VetMIg © (14.05.02 14:25)
Ну секрет прям какой то.
Давай так ты говоришь нам подробности, включая сообщение об ошибки, а мы тебе помогаем. Ты молчишь и мы молчим.


 
Кулюкин Олег   (2002-05-14 15:41) [21]

2 Anatoly Podgoretsky © (14.05.02 15:23)
Может это коммерческая тайна? :)


 
VetMIg   (2002-05-15 02:08) [22]

Ок... Во-первых, строчки кода, пример...

Нужно закрыть About_Form.

procedure TAbout_Form.Image3Click(Sender: TObject);
begin
PlaySound("sound\menu_back.wav", 0, Snd_FileName);
About_Form.Visible:= False;
About_Form.Free;
Main_Form.Visible:= True;
Main_Form.SetFocus;
end;

Теперь ошибка:

Project Project1.exe raised exception class EAccessViolation with message "Access violation at address 0043F419 in module Project1.exe". Read of address 00D34EBD

Все, что просили.


 
Fay   (2002-05-15 02:20) [23]

Круто !!!


 
Slym   (2002-05-15 06:51) [24]

Гасишь форму, а в его методе продолжаешь -
Main_Form.Visible:= True;
Main_Form.SetFocus;
попробуй фри вставить в конец :)


 
Alx2   (2002-05-15 08:07) [25]

Free из самого себя - не выход. Release?


 
Мальфет   (2002-05-15 08:54) [26]

VetMIg, извини, но над стилем тебе надо поработать...

По сабжу: Абсолютно неправомощно использовать процедуры освобождения объекта из самого объекта.


 
KSergey   (2002-05-15 09:40) [27]

Все что вам отвечено - абсолютно верно (как будто кто-то в том сомневался ;)
Я бы посоветовал сделать так:

procedure TAbout_Form.Image3Click(Sender: TObject);
begin
PlaySound("sound\menu_back.wav", 0, Snd_FileName);
Close;
// а вот цель след. вдух строк не ясна:
// а что, MainForm была скрыта в момент показа About?
// А зачем?! Ну впрочем есть надо - можно и оставить эти строки
// Main_Form.Visible:= True;
// Main_Form.SetFocus;
end;

// и обязательно далее: облаботчик OnClose формы About:

procedure TAbout_Form.FormCloseSender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;


В моем понятии все это очень корректно сработает. Или есть возражения?

Хотя вообще-то я бы вообще все это сделал не так. Где-то же, как я понимаю, форма About создается? Вот в этом месте я бы сделал так (предположим, что это нажатие на кнопку в главной форме):

// внимание: здесь не присваивается значение переменной About_Form
// А оно вообще-то надо?! Обычно и без этого можно обойтись
with TAbout_Form.Create (Self) do
try
ShowModal;
finally
Free;
end;


Тогда и обработчик клика на картинке преобразуется в

procedure TAbout_Form.Image3Click(Sender: TObject);
begin
PlaySound("sound\menu_back.wav", 0, Snd_FileName);
Close;
// ну если очень надо - можно раскомментировать две след. строчки
// Main_Form.Visible:= True;
// Main_Form.SetFocus;
end;


Вот и все!
К стати, в приведенной конструции, которую я везде использую, так же никогда не пользовал Release. Пока везло.. Возможно, этому есть объяснение, но я его не знаю. Может кто-либо просветит? (т.к. вроде как аргументы в пользу Release выглядят вполне разумными, но может именно в такой конструкции это принципиально уже не важно, т.к. все сообщения уже проехали в момент ShowModal?)


 
koks   (2002-05-15 09:41) [28]

procedure TAbout_Form.Image3Click(Sender: TObject);
begin
PlaySound("sound\menu_back.wav", 0, Snd_FileName);
Close;
Main_Form.Visible:= True;
Main_Form.SetFocus;
end;

procedure TAbout_Form.About_FormOnClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;

Это если у тебя About_Form - не модальная...

Да, кстати, интересно было бы найти, при установки Action := caFree форма РЕАЛЬНО удаляется методом Free или Realease...


 
KSergey   (2002-05-15 09:42) [29]

Скобочка одна выпала:

procedure TAbout_Form.FormClose(Sender: TObject; var Action: TCloseAction);


 
KSergey   (2002-05-15 09:44) [30]

2 koks

А если модальная - то что? Какая разница?


 
leshy   (2002-05-15 09:49) [31]

А почему в TAbout_Form.OnClose нельзя просто поставить Action := caFree, и не задумываться больше над этим. Туда же можно вставить About_Form := nil, чтобы не делать этого где то ещё. Туда же, кстати, можно и Main_Form.Show, вместо Visible и SetFocus.
Хотя, если быть до конца корректным, обнуление переменной формы лучше делать в BeforeDestruction.
Соответственно, закрытие формы производить простым Close.


 
Alex M.A.   (2002-05-15 09:54) [32]

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

procedure TForm1.AboutMenuClick(Sender: TObject);
begin
AboutBox:=TAboutBox.Create(Application);
AboutBox.ShowModal;
end;

procedure TAboutBox.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;


caFree - The form is closed and all allocated memory for the form is freed.


 
Zemal   (2002-05-15 10:20) [33]

VetMlg, ну ты дал! Когда код пишешь мысли практично, представляй как будет работать программа, представляй образно объекты и всё будет хорошо. А в твоём случае, после уничтожения формы как будут работать её события если их нет??? Если кнопка в событии которой выполняются инструкции уже разрушена?
И кстати, метод Free во многих случаях работает без помех, если вы сами не посылаете сообщение окну формы какой-нить "нитью", которая страшно подтормаживает из-за низкого приоритета и не проверяя существование формы шлёт ей месаги. Это называется безолаберность. Пишите процедуры и функции так, что бы потом не думать какой метод вызвать Free или Release. :))) Просто соблюдайте правила хорошего тона в программировании - проверяйте (не ленитесь) все VCL компоненты перед обращением к ним, если есть вероятность, что их нет. :)))
И ещё, VetMlg, как ты думаешь? Объект себя "вешает", потом "встаёт из могилы" и "прощается с роднёй"? Если уж форма себя унечтожает, то позаботься о том, чтобы: во-первых, были унечтожены все объекты в классе этой формы (если ты что-то создаёшь сам), дело всё в том, что если ты создаёшь объект в классе формы, то ты его и должен уничтожить, само приложение не будет разрушать такие объекты и они остаются висеть в памяти, а ты уже не можешь ничего с ними поделать, т.к. теряешь указатель на эти объекты, во-вторых, старайся думать так, как "думает" приложение, пока не научишься представлять как оно работает - ничего из тебя не получется (в смысле: программист ты будешь "примерочный" - который ищет примеры где только можно и составляет приложение из этих кусков, немного их подправив, а потом удивляется откуда ошибки и беспомощно разводит руками).
Мой совет: начинайте с основ, т.е. с объектной модели. Не усвоив это не переходите к изучению методов и т.д., потому что это бесполезно. Без понятия философии классов (наследование и т.д.), нечего дальше даже нос совать. Жаль, что мало в каких книгах хорошо это описывают... сразу начинают учить за "21 день"... и начинаются вопросы в форумах, которые показывают совершенное незнание основ (времени жизни объектов, области видимости и т.д.). Печально смотреть на программеров подготовленных за "21 день", которые потом засыпают форумы вопросами типа "знаю как пользоваться ноздрями, а дышать не могу! почему?"... ДА ПОТОМУ! Лезь в учебники!!!
Блин... бардак... извините друзья! Я просто не выспался сегодня! :) Бошка трещит, а триггера не ждут... :)
Извиняюсь, если лабуду написал, что было в голове то и написал :)... даже перечитывать не охото, тем более исправлять :)... типа: версия "как-есть". гы-гы.
:)))


 
KSergey   (2002-05-15 10:42) [34]

2 Zemal
Чем филосовски умничать - лучше бы выспался. Полезнее бы оно как-то было для всех - меньше подбирать


 
KSergey   (2002-05-15 10:42) [35]

2 Zemal
Чем философски умничать - лучше бы выспался. Полезнее бы оно как-то было для всех - меньше подбирать


 
KilkennyCat   (2002-05-15 11:00) [36]

А вот так делаю я:

При вызове какой либо формы из главной:
begin
About := TAbout.Create(self);
try
About.ShowModal;
Main.hide;
finally
About.Free;
Main.Show;
end;
end;

Разумеется, эта форма не должна создаваться в проекте (кинуть ее в секцию Available forms)

Закрытие формы About
modalresult := mrCancel;
Хотя и не обязательно, если в дальнейшем не обрабатывать это.


 
KilkennyCat   (2002-05-15 11:16) [37]

Тысяча извинений, с хайд и шоу я переборщил :)
Разумеется, визибле нот визибле.


 
Producer   (2002-05-15 13:47) [38]

Не много-ли шума вокруг простого вопросика? Я думаю, что VetMlg отнюдь не с "бронепоезда" и уже давно "в проблеме".


 
KSergey   (2002-05-15 16:11) [39]

2 Producer
А если много - зачем его увеличиваете?

и опять же тема окаазлась интересной, нек. тонкости выискались, так что погорячились вы, Producer.

К тому же никто не ответил пока: правомочно ли использовать Free в такой конструкции

with TAbout_Form.Create (Self) do
try
ShowModal;
finally
Free;
end;

или это приведет таки к возможным ошибкам?
Хоят вот мне как кажется: ну уничтожил я форму, за ней уничтожилось окно, хендл его пропал для системы (неактуален), но сообщения остались. Ну и что? Они проигнорируются - вот и все. Если послать сообщение с отфонарным хендлом - неужели винды AV выкинут? Как-то я сильно сомневаюсь в том... (а вот проверить лень, признаю)

К слову, не поленился сейчас глянул как реализовано Release: как то не совсем понятно на мой вкус...

// 1. Шлет сама себе CM_RELEASE, причем Post"ом - отсюда и выход из этой процедуры сразу, до собственно разрушения
procedure TCustomForm.Release;
begin
PostMessage(Handle, CM_RELEASE, 0, 0);
end;

// 2.А как там у нас реакция на CM_RELEASE устроена?
procedure TCustomForm.CMRelease;
begin
Free;
end;


О, нифига себе! просто уничтожается объект, причем Free и не взирая на оставшиеся, возможно, сообщения! Так что про сообщения, якобы обрабатываемые Relaese до конца - это выдумка, однако.
Да и само назначение/применение Release становится мне не совсем понятным: типа "разрушься на досуге".

К стати, реакция на caFree - просто вызывается Release - вот и все.

Видимо, применение Relеase (равно как и его назначение) - в возможности формы уничтожать полностью саму себя. Что, впрочем, похоже можно сделать и вызвав в любом месте Free, важно чтобы это был последний оператор в методе. Ну и, возможно, не во всех обработчиках так можно сделать - могут, наверное, и проблемы возникнуть, если в OnCreate прям сразу Free вызвать ;)

Прощу прощения, если кого утомил. Буду рад конструктивной критике, коли чего недопонимаю.


 
Fantos   (2002-05-16 11:52) [40]

Позволю заметить, что ПРИНЦИПИАЛЬНОЕ различие в использовании FREE или RELEASE я прочувствовал на собственных "граблях". И заключались они (грабли) в следующем:
- программа подключала DLL-ку (динамически, в отдельном потоке) с вызовом формы из нее (не модально!). В этом модуле шла работа с устройствами через COM-порты... Так вот, если в интерфейсной процедуре из DLL-ки (вы понимаете о чем я?) ставилось удаление формы через FREE, то основная программа ПРИ или ПОСЛЕ выполнения FREELIBRERY - частенько И НЕ ЗАКОНОМЕРНО вываливала ошибку AV ! Причина -- банальное ОТСУТСТВИЕ обработчика очереди сообщений...форма то уже УДАЛЕНА!
А вот когда FREE была заменена на RELEASE, вот тогда все стало нормально работать и закрываться...
Вот Вам и разница, как говорится - "на пальцах"...

Поэтому, для "выписки рецепта" необходимо, сначала, "обдумать" всю связку удаляемых форм и основного модуля(или формы, если хотите)...


 
Tonie   (2002-05-16 12:55) [41]

To KSergey © (15.05.02 16:11)

>PostMessage(Handle, CM_RELEASE, 0, 0);

Ну так в этом и смысл, сообщение CM_RELEASE будет помещено после уже имеющихся в очереди, поэтому и TCustomForm.CMRelease произойдет после того как все оставшиеся сообщения будут обработаны

Кстати Close вызывает Release, поэтому использование Close вместе c ... Action := caFree вполне корректно



procedure TCustomForm.Close;
var
CloseAction: TCloseAction;
begin
if fsModal in FFormState then
ModalResult := mrCancel
else
if CloseQuery then
begin
if FormStyle = fsMDIChild then
if biMinimize in BorderIcons then
CloseAction := caMinimize else
CloseAction := caNone
else
CloseAction := caHide;
DoClose(CloseAction);
if CloseAction <> caNone then
if Application.MainForm = Self then Application.Terminate
else if CloseAction = caHide then Hide
else if CloseAction = caMinimize then WindowState := wsMinimized
else
Release;
end;
end;


 
VetMIg   (2002-05-21 14:34) [42]

Спасибо друзья... Я вдоволь начитался. Обязательно попробую ваши советы. И еще раз спасибо :-))))))



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

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

Наверх





Память: 0.57 MB
Время: 0.006 c
1-7087
SevaNews
2002-05-22 00:08
2002.06.03
Вопрос по кодировке КАК поменять кодировку с win12 ->KOI8-R?


3-6887
ogu
2002-05-09 23:44
2002.06.03
Как сохранить ADOTable в формате MSAccass (*.mdb)


1-7034
SPeller
2002-05-21 15:32
2002.06.03
Процедурные типы


14-7178
BigBadMutuh
2002-04-24 16:29
2002.06.03
Вопрос про TColorBox.


14-7205
lipskiy
2002-04-25 23:15
2002.06.03
Вопрос только Питерцам!





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский