Модальные формы довольно распространены в Delphi. Их основное удобство заключается в легкости контроля жизненного цикла формы (Create - ShowModal - Free), плюс мгновенное получение результата выбора пользователя (ModalResult). Не буду говорить о том, что приложение, перегруженное модальными формами отталкивает пользователя, это отдельная тема.
Однако довольно часто встречается, что программисты такие формы освобождают не совсем корректно, используя метод Release, вместо Free. В простых случаях это не страшно, в более сложных может привести иногда к странным "глюкам", а иногда и к AV (Access Violation).
Для начала разберёмся, что такое Release, как он работает и когда его надо использовать.
Метод формы Release не уничтожает форму немедленно, а посылает самой же себе сообщение CM_RELEASE. Посылает через PostMessage, т.е. ставит сообщение в очередь и возвращает управление программе. Затем, обработав все сообщения и получив CM_RELEASE, форма вызывает себе Free.
Вот что об этом методе написано в справке Delphi (в переводе на русский):
- Release не уничтожает форму до тех пор, пока все обработчики событий формы и обработчики событий компонент формы не закончат своё выполнение. Release также гарантирует, что все сообщения, стоящие в очереди формы, будут обработаны до того, как форма будет освобождена.
Здесь же сказано:
- Обработчикам событий формы или компонентов формы стоит использовать Release вместо Free, чтобы уничтожение формы не привело к ошибкам доступа к памяти.
Казалось бы всё понятно: Release нужен чтобы избежать возможных AV при освобождении формы. Однако не все программисты внимательны, и берут за правило: "формы всегда уничтожать только через вызов метода Release". Это правило не верно, и я объясню почему.
Вернёмся к модальным формам и рассмотрим такой пример.
procedure TMyForm.OnButtonClick(Sender: TObject); var SomeObject: TSomeObject; begin SomeObject := TSomeObject.Create; try with TSomeForm.Create(Self) do try SomeProperty := SomeObject; // SomeProperty - свойство только что созданной формы ShowModal; finally Release; // <- Обратим внимание на эту строку! end; finally SomeObject.Free; end; end;
В этом примере модальная форма работает с неким SomeObject, за создание и уничтожение которого отвечает вызывающая сторона. Вызывающая же сторона (по отношению к модальной форме) отвечает и за создание и за уничтожение самой модальной формы. На первый взгляд всё красиво.
Однако, если в обработчике OnDestroy модальной формы попытаться обратиться к SomeObject, произойдёт AV. Заменив же Release в строке 12 на привычный нам Free получится избежать подобных ошибок.
Для сторонников метода Release хочу отметить, что вызов Free в данном примере не противоречит справке (где расписано, в каких именно местах стоит использовать Release). Почитайте справку ещё раз и обратите внимание на слова "обработчики событий формы" и "обработчики событий компонент формы".
3 коммент.:
Спасибо. Век живи - век учись.
Спасибо!
Несколько раз пробовал использовать Release по правилу "Release должен быть всегда лучше чем Free", сталкивалася с ошибками и снова возвращался к Free.
Ставим Release в событии onClose, а в приведенном обработчике ничего писать не надо
Отправить комментарий