TForm::Release()
Такая проблема, я создаю окна и помешаю их в стек
TMyForm * MyForm = new TMyForm(this);
Stack->Push(MyForm);
а при закрытии окна я вызываю Pop(), поскольку у меня все окна перекрывают друг друга, т.е. нельзя переключится между окнами, то при вызове Pop() как раз будет закрыто верхнее окно.
void TMain::Pop()
{
--wCount;
if (wCount < 0 )
{
ShowMessage("?????? ???????? ????");
return;
}
Wins[wCount]->Close();
Wins[wCount]->Release();
Wins[wCount] = NULL;
}
Вот такая функция.
Но на некоторых окнах, при закрити окна уже, после вызова функции Pop() (я пошагово в отдладчике смотрел), получается исключение
---------------------------
Debugger Exception Notification
---------------------------
Project Viewer.exe raised exception class EAccessViolation with message 'Access violation at address 00000000. Read of address 00000000'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
Что за хрень? если в дебаггере смотреть то он код ассемблера дальше выдает и типа исключение тоже там же, т.е. не поймеш в какой строчке кода эта хрень произошла.
За границы массива на котором реализован Стек я не выхожу.
Здрасте все,
Такая проблема, я создаю окна и помешаю их в стек
TMyForm * MyForm = new TMyForm(this);
Stack->Push(MyForm);
а при закрытии окна я вызываю Pop(), поскольку у меня все окна перекрывают друг друга, т.е. нельзя переключится между окнами, то при вызове Pop() как раз будет закрыто верхнее окно.
void TMain::Pop()
{
--wCount;
if (wCount < 0 )
{
ShowMessage("?????? ???????? ????");
return;
}
Wins[wCount]->Close();
Wins[wCount]->Release();
Wins[wCount] = NULL;
}
Вот такая функция.
Но на некоторых окнах, при закрити окна уже, после вызова функции Pop() (я пошагово в отдладчике смотрел), получается исключение
---------------------------
Debugger Exception Notification
---------------------------
Project Viewer.exe raised exception class EAccessViolation with message 'Access violation at address 00000000. Read of address 00000000'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
Что за хрень? если в дебаггере смотреть то он код ассемблера дальше выдает и типа исключение тоже там же, т.е. не поймеш в какой строчке кода эта хрень произошла.
За границы массива на котором реализован Стек я не выхожу.
В BCB только delete Wins[wCount] и никаких Free() и Release()
В BCB только delete Wins[wCount] и никаких Free() и Release()
Здесь даже проблема не столько в BCB - ведь для создания формы ты используешь new. Если я верно с этим разобрался Страуструп специально ввел операторы new и delete, что бы гарантировать при инициализации вызов конструктора, а соответственно при разрушении - деструктора. для функций типа Release() это никто не гарантировал. Это первое. Второе - сто в гору - деструктор ты для формы не определял - значит должен отработать деструктор базового класса. Он это и пытается сделать - но объект уже разрушен...
Здрасте все,
Такая проблема, я создаю окна и помешаю их в стек
TMyForm * MyForm = new TMyForm(this);
Stack->Push(MyForm);
а при закрытии окна я вызываю Pop(), поскольку у меня все окна перекрывают друг друга, т.е. нельзя переключится между окнами, то при вызове Pop() как раз будет закрыто верхнее окно.
void TMain::Pop()
{
--wCount;
if (wCount < 0 )
{
ShowMessage("?????? ???????? ????");
return;
}
Wins[wCount]->Close();
Wins[wCount]->Release();
Wins[wCount] = NULL;
}
Вот такая функция.
Но на некоторых окнах, при закрити окна уже, после вызова функции Pop() (я пошагово в отдладчике смотрел), получается исключение
---------------------------
Debugger Exception Notification
---------------------------
Project Viewer.exe raised exception class EAccessViolation with message 'Access violation at address 00000000. Read of address 00000000'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
Что за хрень? если в дебаггере смотреть то он код ассемблера дальше выдает и типа исключение тоже там же, т.е. не поймеш в какой строчке кода эта хрень произошла.
За границы массива на котором реализован Стек я не выхожу.
Окна уже в методе Close могут себя удалять. Поэтому Release делать не обязательно. Прваильней делать так:
if(Wins[wCount])
{
Wins[wCount]->Release();
Wins[wCount] = NULL;
}
В BCB только delete Wins[wCount] и никаких Free() и Release()
Все дело в том что если написать:
TMyForm * f = new TMyform(this);
f->ShowModal();
delete f;
то как раз на третьей строчке и вылетит исключение, поэтому я посмотрел в help'e BCB на тему деструктора TForm:
Frees the memory associated with the TForm object.
__fastcall virtual ~TForm(void) { }
Description
Do not explicitly destroy form objects. Instead, use the Release method to free a form. Release waits until all event handlers have finished executing before destroying the form.
Т.е. как я понял delete нельзя вызывать, а надо Release.
Окна уже в методе Close могут себя удалять. Поэтому Release делать не обязательно.
Методом научного тыка выяснилось следующее:
Все работает если форму вызывать не ShowModal()
а Show(), и в обработке OnClose() делать
Pop().
Хотелось бы разобратся все таки, как правильно удалять формы и почему в одном случае работает а в другом нет?
{
fmAddOrEditEx = new TfmAddOrEditEx(Application);
fmAddOrEditEx->ShowModal();
delete fmAddOrEditEx;
}
Ни каких проблем не возникает. В примерах билдера есть пример обработки события OnClose:
в таком случае удаление делать уже не нужно.
Хотелось бы разобратся все таки, как правильно удалять формы и почему в одном случае работает а в другом нет?
В обработчике OnClose формы есть параметр Action = caFree/caHide/caNone/caMinimize.
По умолчанию, она разная, для разных типов форм.
Все дело в том что если написать:
TMyForm * f = new TMyform(this);
f->ShowModal();
delete f;
то как раз на третьей строчке и вылетит исключение, поэтому я посмотрел в help'e BCB на тему деструктора TForm:
Frees the memory associated with the TForm object.
__fastcall virtual ~TForm(void) { }
Description
Do not explicitly destroy form objects. Instead, use the Release method to free a form. Release waits until all event handlers have finished executing before destroying the form.
Т.е. как я понял delete нельзя вызывать, а надо Release.
Методом научного тыка выяснилось следующее:
Все работает если форму вызывать не ShowModal()
а Show(), и в обработке OnClose() делать
Pop().
Хотелось бы разобратся все таки, как правильно удалять формы и почему в одном случае работает а в другом нет?
Модальные формы по своей природе не предпологают свое дальнейшее использование после закрытия, поэтому по методу клозе они и делают еще и релизе
Модальные формы по своей природе не предпологают свое дальнейшее использование после закрытия, поэтому по методу клозе они и делают еще и релизе
Откуда информация? т.е. код, приведенный ниже недопустим?
if(fmModal->ShowModal()==mrOk){
...
int W = fmModal->MyProp;
...
}
delete fmModal;
Ты чтото перепутал.
Откуда информация? т.е. код, приведенный ниже недопустим?
if(fmModal->ShowModal()==mrOk){
...
int W = fmModal->MyProp;
...
}
delete fmModal;
Ты чтото перепутал.
Допустим, если fmModal создавалась как Application->CreateForm(...)
Допустим, если fmModal создавалась как Application->CreateForm(...)
Ну и что - не важно как она создавалась - важно как отображается....:D
При закрытии модальной формы ее разрушения не происходит в событии OnClose, как впрочем и любой другой, если не вызван оператор delete или свойство Action не было установлено в caFree. Или если не разрушен владелец данной формы.
Ну и что - не важно как она создавалась - важно как отображается....:D
При закрытии модальной формы ее разрушения не происходит в событии OnClose, как впрочем и любой другой, если не вызван оператор delete или свойство Action не было установлено в caFree. Или если не разрушен владелец данной формы.
Во - во владелец. В VCL именно владелец отвечает за дестрой. А если ты сдлеал new и владелец у тебя NULL, то за delete отвечает сама форма и по close она себя уберет.
Во - во владелец. В VCL именно владелец отвечает за дестрой. А если ты сдлеал new и владелец у тебя NULL, то за delete отвечает сама форма и по close она себя уберет.
Александр, богатая фантазия - дело хорошее, но первым был барон, который сам себя за волосы из болота вытащил...:) Если владелец явно не указан - то это приложение. И форма будет разрушена только по завершении работы приложения...
А где можно об этом всем почитать, а то во всех книжках по билдеру которые мне попадались, только и описывается, как создавать нотепады да калькуляторы... а сам механизм ни где не описывается.Все на уровне нажмите туда получите то.
Спасиба, буду переваривать информацию.
А где можно об этом всем почитать, а то во всех книжках по билдеру которые мне попадались, только и описывается, как создавать нотепады да калькуляторы... а сам механизм ни где не описывается.Все на уровне нажмите туда получите то.
Читай "Руководство разработчика". Вышла неплохая книжка, чтото типа "углубленные приемы программирования в билдере" - не помню точно названия - Архангельского и Томилина. Справка. Страуструп. Исходники. Страуструп пожалуй в начале.
Александр, богатая фантазия - дело хорошее, но первым был барон, который сам себя за волосы из болота вытащил...:) Если владелец явно не указан - то это приложение. И форма будет разрушена только по завершении работы приложения...
К вопросу о фантазии и баронах (VCL sources forms.pas)
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 [color=red]Release;[/color]
end;
end;
К вопросу о фантазии и баронах (VCL sources forms.pas)
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 [color=red]Release;[/color]
end;
end;
Вот ты не угомонный...:)
Ну посмотри внимательней - это происходит только в том случае если...
[color=red]if CloseAction <> caNone[/color] и при этом CloseAction не caHide или caMinimize
т.е. если в событии OnClose у тебя записано -
Action = caFree - или же форма является главной для приложения - только тогда происходит разрушения объекта (ну и естественно если ты в том же событии не вызвал delete - ну тогда от ошибок доступа сам отбивайся...:) ). Во всех остальных случаях деструктор не вызывается и удалить объект из памяти можно только вызвав delete. И надо сказать даже в этом случае память системе не возвращается до завершения программы. Просто программа использует ее под свои нужды. Вот с этим я еще не разобрался.
Вот ты не угомонный...:)
Ну посмотри внимательней - это происходит только в том случае если...
[color=red]if CloseAction <> caNone[/color] и при этом CloseAction не caHide или caMinimize
т.е. если в событии OnClose у тебя записано -
Action = caFree - или же форма является главной для приложения - только тогда происходит разрушения объекта (ну и естественно если ты в том же событии не вызвал delete - ну тогда от ошибок доступа сам отбивайся...:) ). Во всех остальных случаях деструктор не вызывается и удалить объект из памяти можно только вызвав delete. И надо сказать даже в этом случае память системе не возвращается до завершения программы. Просто программа использует ее под свои нужды. Вот с этим я еще не разобрался.
Вот и выходит говорим об одном и том-же, только по разному. Проблема коммуникации. А то что указатель не чистится - это правда. Но я думаю, что память в кучу всетаки возврашается. У Борланда всегда было свое управление кучей.
ЗЫ Попробовал сделать два раза подряд new, delete. У меня очень интересные результаты получились. Оба раза this у формы один и тот же. Опитимизация мать....
Вот и выходит говорим об одном и том-же, только по разному. Проблема коммуникации.
Ну если так - разобрались...:)
А то что указатель не чистится - это правда. Но я думаю, что память в кучу всетаки возврашается. У Борланда всегда было свое управление кучей.
ЗЫ Попробовал сделать два раза подряд new, delete. У меня очень интересные результаты получились. Оба раза this у формы один и тот же. Опитимизация мать....
Память в кучу возвращается - но только по завершении приложениия. Я с этим столкнулся как то, мне надо было в вектор загнать куевую тучу картинок в вектор, что бы не читать с диска. И я был приятно удивлен, что не смотря на все мои изыски( как я только не пробовал все это удалять...:) и "умные" указатели пытался использовать - ну может не очень умно использовал ) моя програмулина радосно отхавывала куски памяти и даже не кривилась. И желания возвращать ее что то я не заметил...:) Точнее возвращала - к примеру 7М из 50М...Так я с этим до конца и не разобрался - пришлось обходиться без вектора.
К вопросу о фантазии и баронах (VCL sources forms.pas)
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 [color=red]Release;[/color]
end;
end;
Пример Дельфевого кода.
Pascal и C несколько разные языки.
Соответсвенно и разница в работе с классами - как небо и земля.
Так что в C++ - никаких Release и.т.п.
Создать класс - new - удалить - delete. Никак иначе.
Пока не сделать delete - класс у тебя по-любому будет присутствовать. Никакие Release и Close этому не помогут.
Так что в C++ - никаких Release и.т.п.
Создать класс - new - удалить - delete. Никак иначе.
Хм...помоему в столь категоричной форме это не верно. Во первых, прежде чем писать стоит посмотреть по использованию памяти три варианта:
if(fmModal->ShowModal()==mrOk)ShowMessage("Ok");
delete fmModal;
if(fmModal->ShowModal()==mrOk)ShowMessage("Ok");
fmModal->Free();
if(fmModal->ShowModal()==mrOk)ShowMessage("Ok");
fmModal->Release();
- может тебя это удивит - но очистка памяти происходит во всех трех случаях. И все три случая вполне корректно отрабатывают. Ошибка у парня вылетала не в связи с тем, функцию ли или оператор он использовал для удаления. Скорее всего, он просто нах%евертил гдето в реализации сего - т.е. или пытался удалять удаленный объект, вариантов тут много.
Другое дело, надо ли полагатся на реализацию функций, или лучше использовать нормальный синтаксис языка - тут уже на усмотрение разработчика.
Кроме того, не нужно ставить знак равенства между ANSI C++ и C++Bilder.
Пример Дельфевого кода.
Pascal и C несколько разные языки.
Соответсвенно и разница в работе с классами - как небо и земля.
Так что в C++ - никаких Release и.т.п.
Создать класс - new - удалить - delete. Никак иначе.
Пока не сделать delete - класс у тебя по-любому будет присутствовать. Никакие Release и Close этому не помогут.
Языки то разные да VCL один и написан он на Паскале.