Форум: "Основная";
Текущий архив: 2007.05.20;
Скачать: [xml.tar.bz2];
ВнизПроблема удаления объектов в 0-ом элемента коллекции (TCollectio) Найти похожие ветки
← →
duhast © (2007-03-22 12:41) [0]Кто-нибудь работал тесно с коллекциями в Делфи?
У меня возникла такая проблема - существют 2 созданнх мной класса
TMNSB_DetailObjItem и TMNSB_DetailObjCollection. У элемента коллекции есть 2 поля тип объекта и сам объект. Объект создаётся и инициализируется вне (на стороне :) ) НУ в конце-концов мне, при удалении коллекции, нужно освобождать память от объекта в элементе коллекции. Так вот проблема возникает при уделении 0-го элемента коллекции (как известно дестрой происходит с n-го элемента по 0-й) - память из под него просто не освобождается.
Вот код описания:
TMNSB_DetailObjItem = class (TCollectionItem)
private
FObjClass: TClass;
FObj: TObject;
public
property ObjClass: TClass read FObjClass write FObjClass;
property Obj: TObject read FObj write FObj;
{constructor/destructor}
destructor Destroy; override;
end;
TMNSB_DetailObjCollection = class (TCollection)
private
function GetItem(Index: Integer): TMNSB_DetailObjItem;
procedure SetItem(Index: Integer; Value: TMNSB_DetailObjItem);
public
function Add: TMNSB_DetailObjItem;
property Item[Index: integer]: TMNSB_DetailObjItem read GetItem write SetItem; default;
end;
Код деструктора:
destructor TMNSB_DetailObjItem.Destroy;
begin
Obj.Free;
// Если 0-й то проверям что там с ним
If Self.Index = 0 then
Begin
// If Assigned (obj) then obj.Free
Showmessage(Obj.ClassName);
end;
inherited;
end;
Вот такой вот код, если раскоментировать строку If Assigned (obj) then obj.Free - то возникает исключительная ситуация - типа я его уже закосил - проверяю есть ли там что то - есть !! - тогда удали... - там нефига нету и вообще непонятно что там ---> вылет!!!!
Кто с таким сталкивался пожайлуста помогите!!! Или скажите что не так.
← →
clickmaker © (2007-03-22 12:55) [1]а как создание и удаление происходит?
← →
ЮЮ © (2007-03-22 13:00) [2]> Obj.Free;
> // Если 0-й то проверям что там с ним
И чего теперь уже проверять, если уничтожен? А ссылка естестенно остаоась. И Assigned (obj) будет true.
← →
Плохиш © (2007-03-22 13:01) [3]Да и текст исключения не помешает в оригинале.
← →
ЮЮ © (2007-03-22 13:09) [4]> Объект создаётся и инициализируется вне (на стороне :) )
>
А может они (объекты) и уничтожаются не стороне? И к моменту уничтожения элементов коллекции уже имеем битые ссылки?
← →
duhast © (2007-03-22 14:55) [5]Коллекция заполняется в др. модуле, в поле эл-та кол-и записывается объект приведённый к типу Tobject (не важно где и как он создаётся главное что коллекция иммет ссылки на все эти объекты, тобиж она ими про инициализирована)
Вот пример считывания данных их полей коллекции:
O: Tobject;
.......................
if DCE.GetCollectRef then
Begin
with DCE.DomainByName("ref").DmnDetailCollection do
begin
O := TMNSBObject(item[0].Obj as item[0].ObjClass);
free;
Edit1.text := TMNSBObject(o).DomainByName("2").DmnValue;
end;
Так вот когда Итем не 0-й то прога удачно вылетает при обращении к объекту
(Error (EAccessViolation): Access viokation at adress --- ну короче понятно), а вот когда Итем 0-й то все отлично отрабатывается, без всяких глюков.
Причем в коллекции 4 элемента и деструктор срабатывает тоже 4-и раза и 0-й элемнт якобы тоже грохает, но блин как оказывается - нет.
← →
duhast © (2007-03-22 15:08) [6]Коллекция грохает только свои элементы, а об том что создано в элементе коллекции она не заботится (проверено!!!!), поэтому и дистрою. После удаления коллекции при обращении к преждевременно сохранёным ссылкам на объект данные сохраняются - тобиж объекты весят в памяти, а вот когда я грохаю принудительно их (см. выше) все бы хорошо - только вот блин 0-й чёто ей ненравится :))))
← →
icWasya © (2007-03-22 17:55) [7]Что за код ???
O: Tobject;
.......................
if DCE.GetCollectRef then
Begin
with DCE.DomainByName("ref").DmnDetailCollection do
begin
O := TMNSBObject(item[0].Obj as item[0].ObjClass); // слишком сложно, хватило бы O := item[0].Obj;
free; // а это к чему????
Edit1.text := TMNSBObject(o).DomainByName("2").DmnValue;
end;
← →
duhast © (2007-03-22 19:22) [8]Незная специфики задачи давайте не обсуждать
Пишу ЕЩЁ РАЗ!!!!
DCE.GetCollectRef - вызов метода объекта
DCE.DomainByName("ref") колекция доменов объекта
DmnDetailCollection - коллекция детализации (с её то элементами я работаю)
Получается "коллекция в коллекции"
O := TMNSBObject(item[0].Obj as item[0].ObjClass); - сохраняю ссылку на объект
FREE - освобождаю память из под коллекции детализации, всё что с ней связано должно быть уничтожено(и item[0].Obj и item[1].Obj и item[n].Obj).
(DCE.DomainByName("ref").DmnDetailCollection), деструктор её элемента уничтажает все связанные с ним объекты!!!!!!
Потом обращаюсь по заранее сохранённой ссылке (O) к объекту 0-го элемената кол-ции и О ЧУДО !!! он ещё существует в отличии от других объектов не 0-го элемента кол-ции - они благополучно уничтожены!!!!!
А вот он радимы сел и не вредим.
← →
duhast © (2007-03-22 19:26) [9]Это всего лиш пример (тест) проверяющий всё ли "загребает" за собой удаляемая коллекция - оказывается не всё, у кого подобный код работает отлично прошу, под бурные авации предоставить его сдесь, пожайлуста!
← →
Юрий Зотов © (2007-03-22 20:10) [10]Н-да...
destructor TMNSB_DetailObjItem.Destroy;
begin
Obj.Free; // Объект убит. Ссылку на него никто не чистил и она осталась.
If Self.Index = 0 then // Зачем тут Self? Он будет и так.
Begin
If Assigned (obj) // Даст true - ведь ссылку никто не чистил.
then obj.Free // Здравствуй, глюк!!!
Showmessage(Obj.ClassName); // Здравствуй, второй глюк!!!
end;
inherited;
end;
Второй глюк к тому же еще и двойной, поскольку обращение к объекту происходит после его аж ДВОЙНОГО уничтожения (LOL!). Впрочем, до второго глюка дело никогда не дойдет - будет валиться на первом.
Что и наблюдается.
Выкиньте этот, извините, бред, и оставьте просто:
destructor TMNSB_DetailObjItem.Destroy;
begin
Obj.Free;
inherited;
end;
И если после этого работать снова не будет, то ищите причину в ДРУГОМ месте. Но уж ТОЧНО не здесь.
← →
Юрий Зотов © (2007-03-22 20:20) [11]if DCE.GetCollectRef then
Begin
with DCE.DomainByName("ref").DmnDetailCollection do
begin
O := TMNSBObject(item[0].Obj as item[0].ObjClass); // ???
free; // *
Edit1.text := TMNSBObject(o).DomainByName("2").DmnValue;
end;
В строке, помеченной звездочкой, грохается коллекция. При этом, согласно коду VCL, она грохает свои Item"ы, а те, согласно коду нашего деструктора, грохают связанные с ними объекты.
После чего переменная O указывает уже не на объект (только что убитый), а куда-то в сторону Луны. И на следующей строке при вызове DomainByName снова получаем "Здравствуй, глюк!".
Поменяйте местами две этих строки.
А строку, помеченную ??? явно писал индус. Это не ошибка, работать она будет - но писал ее явно индус.
А о нулевом/ненулевом индексе забудьте. Они здесь ни при чем. Если они где-то и глючат, то не в этом месте.
← →
duhast © (2007-03-23 01:22) [12]Многоуважаемый Юрий Зотов :) спасибо за пост.
Первоначалньно деструктор так и выглядел:
destructor TMNSB_DetailObjItem.Destroy;
begin
Obj.Free;
inherited;
end;
Данный замути типаIf Assigned (obj) then obj.Free
были добавлены в целях проверить сущиствует ли глюк - на "вылет" это и предполагалось организовать для проверки 0-го элемента.
>В строке, помеченной звездочкой, грохается коллекция. При этом, согласно
>коду VCL, она грохает свои Item"ы, а те, согласно коду нашего деструктора,
>грохают связанные с ними объекты.
Так вот в том то и дело что не все объекты грохаются - 0-й элемент почемуто оставляет за собой "хвост", тобиж при правильно работающем деструкторе
destructor TMNSB_DetailObjItem.Destroy;
begin
Obj.Free;
inherited;
end;
уничтажается все кроме объекта 0-го элемента, т.е. я могу ОБРАТИТСЯ к нему и взять его значени - чего по логике недолжно происходить - так как он УДАЛЁН уже. к 1-му и так далее немогу обратится так как они успешно удалены и происхдоит логичный вылет, а вот последний 0-й весит .
Насчёт строки O := TMNSBObject(item[0].Obj as item[0].ObjClass);- соглаcен :)))
Короче, окончательно привожу пример:
Дупустим в коллекции 4-элемента
if DCE.GetCollectRef then
Begin
with DCE.DomainByName("ref").DmnDetailCollection do
begin
O := item[0].Obj ;// сохраняю
free; // удаляю
Edit1.text := TMNSBObject(O).DomainByName("2").DmnValue; - СТРАННО, НО
РАБОТАЕТ!!!!!!!!!!!! (возвращает значение)
end;
--------------------------------------------------------------
if DCE.GetCollectRef then
Begin
with DCE.DomainByName("ref").DmnDetailCollection do
begin
O := item[1].Obj ;// сохраняю (тоже и для 2-го и 3-го)
free; // удаляю
Edit1.text := TMNSBObject(O).DomainByName("2").DmnValue; - вылетает - так и должно работать (Логично :))
end;
Ещё раз - этот код всего лиш для проверки всё ли удалено вместе с коллекцией, я специально хочу вызвать искл. ситуацию чтобы проверить что все объекты удалены!!!!
← →
DrPass © (2007-03-23 01:44) [13]
> уничтажается все кроме объекта 0-го элемента, т.е. я могу
> ОБРАТИТСЯ к нему и взять его значени - чего по логике недолжно
> происходить - так как он УДАЛЁН уже
Глупости. Если ты удаляешь объект - это не значит, что программа тут же побежит затирать ту память, в которой он лежал. Ни в коем случае. Она просто пометит его участок памяти как свободный, чтобы при случае записать туда что-либо новое. Естественно, после вызова Free сам объект никуда не делся, и если ты сохранил на него ссылку, вполне возможно что он даже будет как-то там работать... некоторое время...
← →
ЮЮ © (2007-03-23 03:46) [14]Edit1.text := TMNSBObject(O).DomainByName("2").DmnValue; - СТРАННО, НО
РАБОТАЕТ!!!!!!!!!!!! (возвращает значение)
> вполне возможно что он даже будет как-то там работать...
> некоторое время...
А ты попробуй не читать, а вызвать метод, который "пишет" в память и посмотри как оно работает
← →
duhast © (2007-03-23 12:02) [15]>А ты попробуй не читать, а вызвать метод, который "пишет" в память и посмотри как оно >работает
Все прекрасно пашет в 0-ом элементе. Записывает значение в якобы уже удаллёный элемент по сохранённой ссылке (после Free ) и его же считывает нормально. - Чего быть не должно.
>Глупости. Если ты удаляешь объект - это не значит, что программа тут же побежит затирать >ту память, в которой он лежал. Ни в коем случае. Она просто пометит его участок памяти как >свободный, чтобы при случае записать туда что-либо новое. Естественно, после вызова Free >сам объект никуда не делся, и если ты сохранил на него ссылку, вполне возможно что он даже >будет как-то там работать... некоторое время...
Так почему же интересно не 0-е элементы не считываются, всё по той жё причине освобождения памяти, а 0-й считывается по вашей так сказать "будет как-то там работать... некоторое время..." - Причём считывается из разных методов (я думал может он в пределах одного метода будет считываться а в других типа уже исчезнет - но это просто глупости :) )
НУ короче я так понял никто из сдесь постивших не сталкивался с такой задачей:
Уничтожить все объекты связанные с эл-том коллекции - тобиж закриэйтить и проинициализировать их в ввыших класах или гденибудь на стороне, а потом при дестрое убить их всех до последнего. Я вот просто был рад что вся созданная система пашет - но когда меня осинило проверить всёли за собой убирает коллекция - оказалось что нет - вот теперь и сижу ломаю голову почему это так. Когда то я столкнулся с глюком в компоненте ADO (работа с рекордсетами - "перебор" рекордсетов), хочу надеятся что с коллекциями не будет глюков в реализации, может гдето я чего не досмотрел - но уже много пересматриваю и всё логично написано и не только я смотрел.
← →
DrPass © (2007-03-23 12:33) [16]
> Так почему же интересно не 0-е элементы не считываются,
> всё по той жё причине освобождения памяти, а 0-й считывается
> по вашей так сказать "будет как-то там работать... некоторое
> время..."
Нам бы твои проблемы...
← →
Gadenysh (2007-03-23 15:35) [17]сделай FreeAndNil, если так уж сильно тебе нужно
← →
Gadenysh (2007-03-23 15:42) [18]и в деструкторе inherited лучше всеже первым ставить
← →
Gadenysh (2007-03-23 15:46) [19]
> Gadenysh (23.03.07 15:42) [18]
> и в деструкторе inherited лучше всеже первым ставить
херню сказал. прошу прощения
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2007.05.20;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.046 c