Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
6-1163506297
Dymytriy
2006-11-14 15:11
2007.05.20
Ограничение траффика в Делфи


15-1177036036
Конференция
2007-04-20 06:27
2007.05.20
Внешний вид Delphi Studio 2005


1-1174550871
Iks
2007-03-22 11:07
2007.05.20
TStringGrid на манер грида в Mozilla Thunderbird


4-1166372263
Repavel
2006-12-17 19:17
2007.05.20
Закрытие доступа на чтение файла


4-1166299301
klimov
2006-12-16 23:01
2007.05.20
Достать текс из класса типа Afx:400000:4048:10013:0:0





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский