Mazzay Опубликовано 20 января, 2019 Поделиться Опубликовано 20 января, 2019 (изменено) Ничего не приходит на ум! Что я делаю не так? Под Windows delete вызывает деструктор, под Android — нет. Unit1.h #ifndef Unit1H #define Unit1H //--------------------------------------------------------------------------- #include <System.Classes.hpp> #include <FMX.Controls.hpp> #include <FMX.Forms.hpp> #include <FMX.Controls.Presentation.hpp> #include <FMX.StdCtrls.hpp> #include <FMX.Types.hpp> //--------------------------------------------------------------------------- class TBoxItem : public TPanel { private: TLabel* tInfo; public: __fastcall TBoxItem(TComponent* Owner, String fText); __fastcall ~TBoxItem(); }; //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // IDE-managed Components TButton *ButtonNew; TButton *ButtonDelete; TLabel *LabelConstructor; TLabel *LabelDestructor; void __fastcall ButtonNewClick(TObject *Sender); void __fastcall ButtonDeleteClick(TObject *Sender); private: // User declarations TBoxItem *bi; public: // User declarations __fastcall TForm1(TComponent* Owner); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif Unit1.cpp #include <fmx.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.fmx" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { bi = NULL; } //--------------------------------------------------------------------------- __fastcall TBoxItem::TBoxItem(TComponent* Owner, String fText) : TPanel(Owner) { Form1->LabelConstructor->Text = Form1->LabelConstructor->Text + " OK"; Parent = (TFmxObject*)Owner; tInfo = new TLabel(this); tInfo->Parent = this; tInfo->TextSettings->HorzAlign = TTextAlign::Center; tInfo->Align = TAlignLayout::Center; tInfo->Text = fText; Height = 32; Align = TAlignLayout::Bottom; } //--------------------------------------------------------------------------- __fastcall TBoxItem::~TBoxItem() { Form1->LabelDestructor->Text = Form1->LabelDestructor->Text + " OK"; delete tInfo; } void __fastcall TForm1::ButtonNewClick(TObject *Sender) { if(!bi) { bi = new TBoxItem(this, "BoxItem"); ButtonNew->Enabled = false; ButtonDelete->Enabled = true; } } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonDeleteClick(TObject *Sender) { if(bi) { delete bi; // под Android деструктор не вызывается, объект не уничтожается (( bi = NULL; ButtonNew->Enabled = true; ButtonDelete->Enabled = false; } } //--------------------------------------------------------------------------- Windows (жму кнопку «new» — получаю «Constructor OK» и панель внизу экрана, жму «delete» — получаю «Destructor OK», панель удаляется) Android (жму кнопку «new» — получаю «Constructor OK» и панель внизу экрана, жму «delete» — «Destructor OK» не получаю, панель НЕ удаляется) C++Builder 10.2.3 Tokyo delete bi; не вызывает деструктор. (( Изменено 20 января, 2019 пользователем Mazzay Цитата Ссылка на комментарий
0 Mazzay Опубликовано 20 января, 2019 Автор Поделиться Опубликовано 20 января, 2019 bi->Parent = NULL; Если это вставить перед delete, как здесь описано, не помогает. Помогает, только если ещё и в конструкторе не указывать владельца «TPanel(NULL)», что не считаю нормальным: __fastcall TBoxItem::TBoxItem(TComponent* Owner, String fText) : TPanel(NULL) Цитата Ссылка на комментарий
0 Mazzay Опубликовано 20 января, 2019 Автор Поделиться Опубликовано 20 января, 2019 (изменено) bi->Parent = NULL; Если это вставить перед delete, как здесь описано, не помогает. Помогает, только если ещё и в конструкторе не указывать владельца «TPanel(NULL)», что не считаю нормальным: __fastcall TBoxItem::TBoxItem(TComponent* Owner, String fText) : TPanel(NULL) ////////////////// В результате остановился на таком варианте, но он мне тоже не нравится: bi->Parent = NULL; #if defined(__ANDROID__) || defined(__APPLE__) bi->DisposeOf(); #endif delete bi; bi = NULL; Изменено 20 января, 2019 пользователем Mazzay Цитата Ссылка на комментарий
0 krapotkin Опубликовано 23 января, 2019 Поделиться Опубликовано 23 января, 2019 может, доки прочесть? в мобильных платформах используется ARC поэтому, пока есть хоть одна ссылка на объект, он не уничтожается зато, когда ссылок нет, он уничтожается самостоятельно вызов Delete для компонента нужен для сохранения кросс-платформенной совместимости в Windows он работает, в ARC - пустой а принудительный вызов деструктора скорее всего только навредит, ибо архитектурный косяк прикрывается костылем... kami и Mazzay 1 1 Цитата Ссылка на комментарий
0 Mazzay Опубликовано 23 января, 2019 Автор Поделиться Опубликовано 23 января, 2019 2 часа назад, krapotkin сказал: может, доки прочесть? в мобильных платформах используется ARC поэтому, пока есть хоть одна ссылка на объект, он не уничтожается зато, когда ссылок нет, он уничтожается самостоятельно вызов Delete для компонента нужен для сохранения кросс-платформенной совместимости в Windows он работает, в ARC - пустой а принудительный вызов деструктора скорее всего только навредит, ибо архитектурный косяк прикрывается костылем... Выходит, без условной компиляции не обойтись? В деструкторах у меня уничтожаются все дочерние объекты, что в свою очередь должно убирать их с экрана, например. Писать вместо деструкторов функции типа «Hide», а память пусть остаётся занятой? Цитата Ссылка на комментарий
0 Mazzay Опубликовано 23 января, 2019 Автор Поделиться Опубликовано 23 января, 2019 Или как мне сделать, чтобы ссылок на объект не осталось, и он уничтожился? Этого недостаточно: bi->Parent = NULL; Цитата Ссылка на комментарий
0 krapotkin Опубликовано 23 января, 2019 Поделиться Опубликовано 23 января, 2019 .RefCount дает количество ссылок на объект, если <>0 значит вы еще не все ссылки удалили Если компонент создан aa := TMyComp.Create(OwnerComponent) то как минимум нужно еще и удалить его у владельца. про удаление компонентов тут 8 страниц недавно написали Если вы создаете его динамически, то не указывайте владельца, тогда Component->Parent = NULL; FreeAndNil(Component); будет достаточно Цитата Ссылка на комментарий
0 Mazzay Опубликовано 23 января, 2019 Автор Поделиться Опубликовано 23 января, 2019 Parent = NULL не могу. Мой объект — это компонент, который размещается на этом Parent. Можно сделать Owner = NULL, но это как-то, ИМХО, неправильно. Цитата Ссылка на комментарий
0 krapotkin Опубликовано 24 января, 2019 Поделиться Опубликовано 24 января, 2019 вот проверил специально. C++ нет у меня но думаю, не отличается ничем b2 := TButton.Create(nil); b2.Parent := Self; b2.SetBounds(50,50,150,30); потом m1.Lines.Add(inttostr(b2.RefCount)); b2.Parent:=NIL; m1.Lines.Add(inttostr(b2.RefCount)); FreeAndNil(b2); // <-- тут попадает в деструктор для проверки TButton=class(FMX.StdCtrls.TButton) public destructor Destroy; override; end; destructor TButton.Destroy; begin ; inherited; // <--- breakpoint here end; если создавать TButton.Create(Self) то нужно больше движений. Просто не нужно так делать )))) Цитата Ссылка на комментарий
0 Mazzay Опубликовано 24 января, 2019 Автор Поделиться Опубликовано 24 января, 2019 1 час назад, krapotkin сказал: если создавать TButton.Create(Self) то нужно больше движений. Просто не нужно так делать )))) Я и писал: В 20.01.2019 в 19:31, Mazzay сказал: Помогает, только если ещё и в конструкторе не указывать владельца «TPanel(NULL)», что не считаю нормальным: __fastcall TBoxItem::TBoxItem(TComponent* Owner, String fText) : TPanel(NULL) 21 час назад, Mazzay сказал: Можно сделать Owner = NULL, но это как-то, ИМХО, неправильно. Почему не нужно передавать указатель на себя потомку? Цитата Ссылка на комментарий
0 krapotkin Опубликовано 24 января, 2019 Поделиться Опубликовано 24 января, 2019 он и не потомок вовсе. там архитектура через ... если ARC все равно все удалится когда удалится Parent Цитата Ссылка на комментарий
0 Mazzay Опубликовано 29 января, 2019 Автор Поделиться Опубликовано 29 января, 2019 В 24.01.2019 в 13:08, krapotkin сказал: если создавать TButton.Create(Self) то нужно больше движений. Кстати, в TComponent Owner объявлен как «unsafe». Почему тогда Create(Self) увеличивает счётчик ссылок дополнительно ещё на единицу? class PASCALIMPLEMENTATION TComponent : public TPersistent { ... private: __unsafe TComponent* FOwner; ... public: __property TComponent* Owner = {read=FOwner}; ... }; Цитата Ссылка на комментарий
0 Mazzay Опубликовано 29 января, 2019 Автор Поделиться Опубликовано 29 января, 2019 (изменено) Или вот, в случае с Delphi: type TComponent = class(TPersistent, IInterface, IInterfaceComponentReference) private [weak] FOwner: TComponent; [weak] FOwner Изменено 29 января, 2019 пользователем Mazzay Цитата Ссылка на комментарий
0 d7d1cd Опубликовано 29 января, 2019 Поделиться Опубликовано 29 января, 2019 (изменено) 4 часа назад, Mazzay сказал: Кстати, в TComponent Owner объявлен как «unsafe». Почему тогда Create(Self) увеличивает счётчик ссылок дополнительно ещё на единицу? Owner объявлен как __unsafe для того, чтобы объекты не увеличивали счетчик ссылок у их владельцев. То есть, это для того, чтобы когда мы пишем, например: TButton *btn = new TButton(Form1), то счетчик ссылок у Form1 не изменился. Когда мы указываем владельца при создании объекта, то он (создаваемый объект), попадает в список того, чем владеет владелец, поэтому счетчик ссылок создаваемого объекта увеличивается. Изменено 29 января, 2019 пользователем d7d1cd Mazzay 1 Цитата Ссылка на комментарий
0 krapotkin Опубликовано 29 января, 2019 Поделиться Опубликовано 29 января, 2019 Причем сразу на 2 )) каюсь, я не стал выяснять почему Mazzay 1 Цитата Ссылка на комментарий
0 Mazzay Опубликовано 29 января, 2019 Автор Поделиться Опубликовано 29 января, 2019 25 минут назад, krapotkin сказал: Причем сразу на 2 )) каюсь, я не стал выяснять почему Во-во. А мне надо освободить память из-под объекта. Какие ещё ссылки на него, которые запомнил Владелец, обнулить? Цитата Ссылка на комментарий
0 d7d1cd Опубликовано 29 января, 2019 Поделиться Опубликовано 29 января, 2019 (изменено) Счётчик увеличивается на 2 потому что одну ссылку хранит владелец, а вторую указатель bi. Тут я не прав. Есть статья Бровина Ярослава. Там сказано, что каждый компонент с фокусом получает дополнительную ссылку. Я проверил, так происходит только тогда, когда при создании объекта указывается его владелец. Поэтому не указывай владельца при создании объекта. Владелец нужен только для автоматического удаления того, кем он владеет при удалении его самого. У тебя же не тот случай. Изменено 29 января, 2019 пользователем d7d1cd Mazzay 1 Цитата Ссылка на комментарий
0 d7d1cd Опубликовано 29 января, 2019 Поделиться Опубликовано 29 января, 2019 (изменено) Вот код добавления кнопки и ее удаление без условной компиляции, который работает и на Windows и на Android, а так же, когда при создании указывается владелец: // btn объявлен в описании класса TForm1 __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { btn = 0; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { btn = new TButton(this); btn->Text = L"Created!"; btn->Parent = this; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { if(!btn) return; btn->Parent = 0; RemoveComponent(btn); delete btn; btn = 0; } Изменено 29 января, 2019 пользователем d7d1cd Mazzay 1 Цитата Ссылка на комментарий
Вопрос
Mazzay
Ничего не приходит на ум! Что я делаю не так?
Под Windows delete вызывает деструктор, под Android — нет.
Unit1.h
Unit1.cpp
Windows (жму кнопку «new» — получаю «Constructor OK» и панель внизу экрана, жму «delete» — получаю «Destructor OK», панель удаляется)
Android (жму кнопку «new» — получаю «Constructor OK» и панель внизу экрана, жму «delete» — «Destructor OK» не получаю, панель НЕ удаляется)
C++Builder 10.2.3 Tokyo
delete bi; не вызывает деструктор. ((
Изменено пользователем MazzayСсылка на комментарий
17 ответов на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.