PDA

Показать полную графическую версию : Destroy себя - ошибка!


e5620
28-02-2010, 16:52
Доброго времени,
Проблема заключается в следующем, пишу для себя компонент, Родителем является TsScrollBox, а дочерними TsPanel (со свойствами alTop).

http://img413.imageshack.us/img413/8399/123ez.png

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

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

DestroyComponents;
FFileStream.Free;
inherited Destroy;


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

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

El Scorpio
01-03-2010, 06:26
после этого осуществляется возврат к концу doCloseClick и "ОШИБКА" доступа к памяти по адресу 0х00000030. »
Всё правильно.
Объёкт уже удалён, соответственно доступ к его полям класса и виртуальным функциям будет вызывать ошибку.
А доступ этот, разумеется, производится где-то в нижних уровнях иерархии классов. Если интересно, где именно - установи "исходники VCL" и поищи :)
Вообще "самоуничтожение" объектов недопустимо просто потому,*что после вызова деструктора метод объекта будет продолжаться

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

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

pva
02-03-2010, 07:25
а если строчки местами поменять - заработает?

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

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

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

P.S.
Заметил что если удалить создание дочерних элементов, т.е. оставить только одну кнопку закрыть, то ошибки нету. »
Возможно, потому что удаление дочерних элементов (адреса которых перечисляются в списке Components) производится автоматически в деструкторе класса TComponents

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

pva
05-03-2010, 07:51
в делфи это самое делает TForm.Release. e5620, интерес к теме не пропал ещё?




© OSzone.net 2001-2012