Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Destroy себя - ошибка! (http://forum.oszone.net/showthread.php?t=168786)

e5620 28-02-2010 16:52 1358157

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



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

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

DestroyComponents;
 FFileStream.Free;
 inherited Destroy;

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

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

El Scorpio 01-03-2010 06:26 1358536

Цитата:

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

Всё правильно.
Объёкт уже удалён, соответственно доступ к его полям класса и виртуальным функциям будет вызывать ошибку.
А доступ этот, разумеется, производится где-то в нижних уровнях иерархии классов. Если интересно, где именно - установи "исходники VCL" и поищи :)
Вообще "самоуничтожение" объектов недопустимо просто потому,*что после вызова деструктора метод объекта будет продолжаться

pva 01-03-2010 07:44 1358551

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

El Scorpio 02-03-2010 05:43 1359258

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

pva 02-03-2010 07:25 1359269

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

El Scorpio 03-03-2010 05:04 1360034

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

pva 03-03-2010 19:42 1360580

Цитата:

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

это код деструктора? а doCloseClick можно посмотреть?

El Scorpio 04-03-2010 05:04 1360845

Цитата:

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

А*после завершения деструктора происходит возвращение в метод doCloseClick удалённого компонента,*из него - в метод doClick удалённой кнопки "Закрыть" :)
Не надо так делать. Согласно принципам ООП, правильнее будет следующий способ.
Метод doCloseClick скрывает компонент, выставляет значение true логическому свойству "DeleteMe" компонента и завершает работу.
Далее вызывается обработчик для события OnIdle (вызывается в моменты "простоя программы"), который перебирает компоненты и удаляет отмеченные.
Или можно поступить проще - не удалять закрываемые компоненты, а лишь скрывать их, обнулять свойства и перемещать в конец списка. Ведь всё равно так или иначе потребуется добавлять новые - тогда по команде "Добавить" программа просто отобразит первый из скрытых, а новый компонент создавать будет только при необходимости

P.S.
Цитата:

Цитата e5620
Заметил что если удалить создание дочерних элементов, т.е. оставить только одну кнопку закрыть, то ошибки нету. »

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

Кстати, не мешало бы почитать справку по методу TComponents.DestroyComponents().
Что он делает? Как он работает? Нужно ли вызывать его вручную? Какие проблемы могут возникнуть при его вызове? :)

pva 05-03-2010 07:51 1361547

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


Время: 10:32.

Время: 10:32.
© OSzone.net 2001-