Delphi - Destroy себя - ошибка!

Ответить
Аватара пользователя
e5620

Delphi - Destroy себя - ошибка!

Сообщение e5620 »

Доброго времени,

Проблема заключается в следующем, пишу для себя компонент, Родителем является TsScrollBox, а дочерними TsPanel (со свойствами alTop).



Изображение



Дочерние элементы создаю динамически, и присваиваются через "добавленную" к родителю функцию Add.



Ошибка заключается в следующем, в каждой строке имеется кнопка "Х" закрыть (удалить строку), При нажатии на нее вызывается встроенное событие doCloseClick, в котором выполняется Free;и переход в destructor:



Код:

Код: Выделить всё

 DestroyComponents;
 FFileStream.Free;
 inherited Destroy;

после этого осуществляется возврат к концу doCloseClick и "ОШИБКА" доступа к памяти по адресу 0х00000030.



Заметил что если удалить создание дочерних элементов, т.е. оставить только одну кнопку закрыть, то ошибки нету.
Аватара пользователя
El Scorpio

Re: Delphi - Destroy себя - ошибка!

Сообщение El Scorpio »

Цитата e5620:



после этого осуществляется возврат к концу doCloseClick и "ОШИБКА" доступа к памяти по адресу 0х00000030.
Delphi - Destroy себя - ошибка!




Всё правильно.

Объёкт уже удалён, соответственно доступ к его полям класса и виртуальным функциям будет вызывать ошибку.

А доступ этот, разумеется, производится где-то в нижних уровнях иерархии классов. Если интересно, где именно - установи "исходники VCL" и поищи Изображение

Вообще "самоуничтожение" объектов недопустимо просто потому,*что после вызова деструктора метод объекта будет продолжаться
Аватара пользователя
pva

Re: Delphi - Destroy себя - ошибка!

Сообщение pva »

что такое FFileStream? как и когда объявлен? поставь перед каждым ...Free код if (...0) debug_string('уже удалён'); а после каждого ...=0. В какой последовательности в делфи идёт уничтожение объектов?

к примеру: в с++ сначала вызывается деструктор объекта, потом только всех его составляющих (таким образом на момент видимости они ещё живы)
Аватара пользователя
El Scorpio

Re: Delphi - Destroy себя - ошибка!

Сообщение El Scorpio »

pva, видишь ли, у него получается так - вызывается деструктор объекта, объект уничтожается, текущий метод завершается, потом управление передаётся в другие методы уже уничтоженного объекта.
Аватара пользователя
pva

Re: Delphi - Destroy себя - ошибка!

Сообщение pva »

а если строчки местами поменять - заработает?
Аватара пользователя
pva

Re: Delphi - Destroy себя - ошибка!

Сообщение pva »

pva, разумеется нет - ведь ошибка происходит в базовых классах при обращении к полям уже удалённого объекта
Аватара пользователя
El Scorpio

Re: Delphi - Destroy себя - ошибка!

Сообщение El Scorpio »

Цитата e5620:



Ошибка заключается в следующем, в каждой строке имеется кнопка "Х" закрыть (удалить строку), При нажатии на нее вызывается встроенное событие doCloseClick, в котором выполняется Free;и переход в destructor:

Код:

DestroyComponents;

FFileStream.Free;

inherited Destroy;
Delphi - Destroy себя - ошибка!




это код деструктора? а doCloseClick можно посмотреть?
Аватара пользователя
El Scorpio

Re: Delphi - Destroy себя - ошибка!

Сообщение El Scorpio »

Цитата e5620:



Ошибка заключается в следующем, в каждой строке имеется кнопка "Х" закрыть (удалить строку), При нажатии на нее вызывается встроенное событие doCloseClick, в котором выполняется Free;и переход в destructor
Delphi - Destroy себя - ошибка!




А*после завершения деструктора происходит возвращение в метод doCloseClick удалённого компонента,*из него - в метод doClick удалённой кнопки "Закрыть"

Не надо так делать.
Согласно принципам ООП, правильнее будет следующий способ.

Метод doCloseClick скрывает компонент, выставляет значение true логическому свойству "DeleteMe" компонента и завершает работу.

Далее вызывается обработчик для события OnIdle (вызывается в моменты "простоя программы"), который перебирает компоненты и удаляет отмеченные.

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



P.S.


Цитата e5620:



Заметил что если удалить создание дочерних элементов, т.е. оставить только одну кнопку закрыть, то ошибки нету.
Delphi - Destroy себя - ошибка!




Возможно, потому что удаление дочерних элементов (адреса которых перечисляются в списке Components) производится автоматически в деструкторе класса TComponents



Кстати, не мешало бы почитать справку по методу TComponents.DestroyComponents().

Что он делает? Как он работает? Нужно ли вызывать его вручную? Какие проблемы могут возникнуть при его вызове? Изображение
Аватара пользователя
pva

Re: Delphi - Destroy себя - ошибка!

Сообщение pva »

в делфи это самое делает TForm.Release. e5620, интерес к теме не пропал ещё?
Ответить

Вернуться в «Программирование и базы данных»