Перейти к содержанию

Вопросы

Как правильно создавать и удалять объекты в run time?
А то создаю так:

c[r] := TCircle.Create(TabItem1);
c[r].Position.X := 1;
c[r].Position.Y := 1;
c[r].Width := 50;
c[r].Height := 50;
c[r].Parent := TabItem1;

И разрушаю так:

c[r].Free;

То в Win всё ок, а на симуляторе iOS объекты не разрушаются, а просто остаются.

Попробовал так:

c[r].Destroy;

Тогда всё на Win опять всё ок, а на симуляторе разрушается, но при попытке снова создать - приложение крашится.

Поделиться сообщением


Ссылка на сообщение

Рекомендуемые сообщения

  • 2

Добрый вечер,
 
Главное, что нужно помнить по теме время жизни объектов - это то, что в мобильных платформах (Android и iOS) процесс удаления объектов отличается от поведения на настольных платформах (Windows и OSX). В мобильных платформах появился механизм ARC (Automatic Reference Counting - автоматический подсчет ссылок). Почитать описание (на английском), как это работает можно тут: Apple Developer. Для нас же, это означает, что все объекты имеют поле - счетчик ссылок (RefCount). Когда счетчик ссылок равен нулю, объект автоматически удаляется. Если кто-то присваивает ссылку на объект, то счетчик автоматически увеличивается на 1.

property RefCount: Integer read FRefCount; // Свойство TObject

Можно ошибочно подумать, что это связано со сборщиком мусора. Однако, это не так. При компиляции, компилятор автоматически вставляет в код служебные команды по увеличению и уменьшению счетчика ссылок. Поэтому объект физически уничтожится в тот момент, когда счетчик ссылок станет равным 0. В то время как сборщик мусора, удаляет объекты по своему внутреннему расписанию.
 
Теперь о вашем вопросе. Когда вы создаете объект и указываете ему родителя, автоматически ваш объект попадает как минимум в список дочерних объектов TabItem1. А значит, автоматически счетчик ссылок на TCircle будет увеличен. Когда вы сохраняете ваш объект в массиве, это опять же автоматически увеличивает счетчик ссылок. Поэтому, чтобы удалить объект есть два способа:
 
1. Вызвать метод TObject.DisposeOf. Это форсирует вызов деструктора, но не очищает память выделенную под объект. Это означает, что выполниться код деструктора, TCircle будет удален из списков, все ресурсы, которые окружность захватила будут распущены. Но сама память, которая была выделена из кучи под его хранение будет распущена, только в момент, когда больше не будет ни одной ссылки. Например, так:

c[r].DisposeOf;
c[r] := nil;

2. Убрать все ссылки, которые указывают на ваш объект. Это приведет к автоматическому удалению объекта. Убрать объект из структуры объектов, путем удаления удаления его из родительcкого контроkа Parent = nil, и затем вызывать Free и занилилить уже ссылку на объект в массиве. 

c[r].Parent := nil;
c[r].Free;
c[r] := nil; // Или FreeAndNil(c[r]), в зависимости от типа c.

Если больше ссылок на ваш объект нету, то данный код автоматически удалит объект c[r].

Дополнение от RAD Studio XE6. В этой версии компилятор автоматически после вызова метода Free очистит указатель на объект. По этой причине дополнительно присваивание nil указателю на объект не требуется на мобильных платформах

var
  A: TObject;
begin
  A := TObject.Create;
  A.Free;
  // В этом месте A = nil на мобильных платформах.
  // На настольных платформах: A указывает на мусор
end; 

Чтобы осталась совместимость с настольными платформами, лучше использовать второй подход.

 

P.S. Никогда не вызывайте деструктор напрямую, вызовом метода Destroy.

Поделиться сообщением


Ссылка на сообщение
Гость
Эта тема закрыта для публикации ответов.

  • Похожий контент

    • От FREEFAR
      Друзья, помогите-таки расставить точки над "И".
      Как же все таки правильно уничтожать динамически создаваемые компоненты TFrame
      Сейчас делаю так:
                        mapFrame.DisposeOf;
                        mapFrame.Parent := nil;
                        mapFrame := nil;
      Вроде удаляется и новый создается.
      Но вот беда.
      Если я создам функцию типа FreeFrame(Frame: TFrame);
      то как бы я ее не вызывал с входным параметром "mapFrame"
      фрейм все равно живет...
      Что не так? Куда копать?
    • От Alex7wrt
      Добрый день.
      Знаю, что на форуме есть несколько тем о том, как удалять объекты под Android и счетчике ссылок, однако использование рекомендаций оттуда мне пока не помогло.
      Суть вопроса: создаю свой класс

       
      type TRext =class(TRectangle) Text: TText; procedure RextMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); procedure RextMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); procedure RextMouseLeave(Sender: TObject); Constructor Create(AOwner: TComponent); override; Destructor Destroy; override; end; type TMyChoose = class Item1, Item2, Item3: TRext; Edits: TEdit; procedure ItemClick(Sender: TObject); procedure OnEditFocus(Sender: TObject; var ACanFocus: Boolean); Constructor Create(Form: TForm); Destructor Destroy; override; end; ..... constructor TRext.Create(AOwner: TComponent); begin inherited Create(AOwner); Text:=TText.Create(Self); Text.Parent:=Self; Text.Align:=TAlignLayOut.Client; Self.Text.OnMouseDown:=RextMouseDown; Self.Text.OnMouseUp:=RextMouseUp; Self.Text.OnMouseLeave:=RextMouseLeave; end; Destructor TRext.Destroy; begin Text.Release; Text:=nil; inherited; end; constructor TMyChoose.Create(Form: TForm); begin inherited Create; Item1:=TRextCreate(Form); Item1.Parent:=Form; Item1.Align:=tAlignLayout.MostLeft; Item2:=TRextCreate(Form); Item2.Parent:=Form; Item2.Align:=tAlignLayout.MostLeft; Item3:=TRextCreate(Form); Item3.Parent:=Form; Item3.Align:=tAlignLayout.MostLeft; Edits:=TEdit.Create(Form); Edits.Parent:=Form; Edits.Align:=tAlignLayout.MostLeft; ......... end; Destructor TMyChoose.Destroy; begin Item1.Release; Item1:=nil; Item2.Release; Item2:=nil; Item3.Release; Item3:=nil; Edits.Release; Edits:=nil; inherited; end; Под Windows все нормально работает и уничтожается. Под Android вызов Destroy у объекта типа TMyChoose не приводит ни к чему.
      Вместо Release и nil использовал также DisposeOf и Nil, а также FreeAndNil - результат аналогичный.
      Как правильно уничтожать составные объекты?
    • От rareMax
      Пасаны - хватай ее: https://www.embarcadero.com/ru/products/delphi/starter/promotional-download
      В след за плюсами начали раздавать делфи стартер. Функционал урезан до жути, но возможно вам много и не нужно?
    • От Дениска
      Пустое приложение. У меня есть формы: А и B.
      А по кнопке создаёт и показывает B и сразу самоуничтожается:
       
      B := TB.Create(nil); B.Show; A.Free;   B в свою очередь делает обратное:   A := TA.Create(nil); A.Show; B.Free;   На Win32 платформе в диспетчере задач память по мере открытия форм не растёт. В iOS 6.1.1 iPhone 3 проследить память я не смог, но после 5-10 открытий форм приложение падает. Вероятнее всего растёт хип (heap).    Почему тогда не работает FREE?? Как правильно освободить память и уничтожить форму в iOS???   Я нашёл ответ. Если на форме есть картинки, то их нужно: Image1.Bitmap.Assign(nil);
    • От xenon54
      procedure TForm1.Button1Click(Sender: TObject); var t : TImage; begin t := TImage.Create(Form1); Memo1.Lines.Add(IntToStr( t.RefCount ) ); t.Parent := form1; t.Width := 50; t.Height := 50; Memo1.Lines.Add(IntToStr( t.RefCount ) ); t.Bitmap.Assign(image1.Bitmap); Memo1.Lines.Add(IntToStr( t.RefCount ) ); t.tag := 11; Memo1.Lines.Add(IntToStr( t.RefCount ) ); end; procedure TForm1.Button2Click(Sender: TObject); var i : Integer; begin Memo1.Lines.Add('---------------------'); for I := 0 to Form1.ComponentCount-1 do begin if Components[i] is TImage then if Components[i].Tag = 11 then begin Memo1.Lines.Add(IntToStr( TImage( Components[i] ).RefCount ) + ' - ' + IntToStr( Components[i].Tag ) ); TImage( Components[i] ).Parent := nil; Memo1.Lines.Add(IntToStr( TImage( Components[i] ).RefCount ) + ' - ' + IntToStr( Components[i].Tag ) ); end; end; end; Вот результат memo после одного клика по button1 и одного клика по button2:
      5 7 7 7 ------------------------------ 9 - 11 10 - 11 После этого делаю еще 1 клик по button2 и получаю:
      7 - 11 10 - 11 Кто-нибудь может объяснить почему RefCount такой большой? Ведь по идее в самом начале на объект ссылается только сама переменная "T" и плюс ссылка в списке "components" у form1. После выхода из процедуры "button1click" локальная переменная(ссылка на объект)  "T" уничтожается и ее можно не считать, я правильно понял? Почему RefCount равен не 2, а 7? Почему если в конце процедуры "button1click" написать "t := nil;" картинка пропадает с формы, ведь на нее куча ссылок если верить RefCount'у Как тогда правильно уничтожить такой объект? Система IOS.
    • От kidrock1
      Всем привет, друзья. Столкнулся со следующей проблемой. Создаётся поток с целью загрузки картинок во время чтения статьи. Да так чтобы основная форма в момент загрузки не была заморожена. Вот код:
      type ThreadHTTP1=class(TThread) private i:integer; public procedure Execute;override; procedure ShowResult1; end; procedure ThreadHTTP1.Execute; var j:integer; begin inherited; try lStream1 := TMemoryStream.Create; Form3.IdHTTP1.Get('http://totalmma.ru/newsupload/8306.jpg',lStream1); except // ShowMessage('no'); end; Synchronize(ShowResult1); end; procedure ThreadHTTP1.ShowResult1; begin ShowMessage(IntToStr(Form3.IDHTTP1.Response.ContentLength)); Form3.Image1.Bitmap.LoadFromStream(lStream1); Form3.Image1.Visible := true; Form3.Caption:=IntToStr(i)+' kbs'; Form3.IdHTTP1.Free; Stream.Free; end; procedure TForm3.Button1Click(Sender: TObject); var MyHTTP1:ThreadHTTP1; begin MyHTTP1 := ThreadHTTP1.Create(False); end; Так вот проблема в следующем. На винде всё работает. А вот когда компилируешь под андройд и переносишь на телефон, при нажатии на кнопке ничего не происходит. Очень прошу помочь, друзья.
    • От rareMax
      Смотрел примеры для новой версии XE6 - и увидел что в блоке try finally для освобождения пишут DisposeOf вместо Free. Можете рассказать в каких случаях писать Free а в каких DisposeOf? Спасибо.
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...