Название: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Unnamed_Hero от Июнь 23, 2008, 13:04 Пытаюсь понять, как корректно работать с tabWidget'ом.
Есть у меня нарисованный в дизайнере виджет. В классе, его описывающем, ещё присутствует некоторое количество вычислений, ради чего внутри класса создаются объекты пары других классов. По нажатию кнопки в главной программе - создаётся новый объект этого виджета и добавляется на новую вкладку tabWidget'a. По нажатию другой кнопки - надо грохнуть текущий виджет из текущей вкладки (и саму вкладку) и удалить из памяти всё то, что он насоздавал. Как это сделать наиболее корректно? В моей реализации у меня гигантские утечки памяти :( Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: lit-uriy от Июнь 23, 2008, 13:28 покажи как сам делаешь
Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: lit-uriy от Июнь 23, 2008, 13:33 чтоб добавить виджет, делай так:
tab->addTab(new MyWidget(this), tr("Вкладка №1")); чтобы удалить текущую вкладку, делай так tab->removeTab( currentIndex ()); Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Unnamed_Hero от Июнь 23, 2008, 14:50 Сделал по написанному. Тоже самое.
Но если верить Assistant'у Цитата: QT Assistant void QTabWidget::removeTab ( int index ) Removes the tab at position index from this stack of widgets. The page widget itself is not deleted Да если верить valdrind'у - объекты классов, которые создаются в конструкторе виджета - не удаляются :( Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Пантер от Июнь 23, 2008, 16:59 А что мешает самому удалить свой виджет?
Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Unnamed_Hero от Июнь 23, 2008, 21:57 А как корректно удалять его?
Мне даже не сколько сам виджет грохнуть надо, сколько подчистить за ним - там создаётся несколько указателей на объекты, и они не удаляются, хотя удаление всех объектов прописал в деструкторе. Наверное, будет проще выложить сюда кусок кода, чтобы было более наглядно. Только предупреждаю сразу - я начинающий, и поэтому код может быть ужасен :) tabWidget->addTab (new char_Sheet (&someData,"sometabname")); в конструкторе char_Sheet создаются объекты других классов для проведения вычислений и преобразований. В деструкторе класса все объявленные объекты delete'аются.... Когда я просто делаю removeTab, то память не освобождается. Если создать массив указателей char_sheet *charArray[]; и говорить delete нужному номеру, то это освобождает часть памяти (удаляется сам виджет, а порождённые им объекты - висят в памяти.) Может, стоит всем классам вычислений ещё прописывать родителя, который их рождает, чтобы они вместе с ним удалялись? Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Пантер от Июнь 23, 2008, 22:00 Да, нужно указывать родителя, который и поубивает всех детей при разрушении. :-D
Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Alex03 от Июнь 24, 2008, 05:44 чтоб добавить виджет, делай так: Вы б определились что у Вас не удаляется, если сама закладка то:tab->addTab(new MyWidget(this), tr("Вкладка №1")); чтобы удалить текущую вкладку, делай так tab->removeTab( currentIndex ()); Код: QWidget * pw = widget(currentIndex ()); Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Red Devil от Июнь 28, 2008, 23:23 Хочу обратить внимание на то, что в QWidget не виртуальный деструктор.
Поэтому перед удалением, необходимо преобразовать указатель к тому обьекту для которого была выделена память изначально, иначе будут утечки памяти. Неправильно : Код: m_pTab->addWidget(new QTextEdit, "New file"); Правильно : Код: m_pTab->addWidget(new QTextEdit, "New file"); Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Sergeich от Июнь 29, 2008, 00:07 Хочу обратить внимание на то, что в QWidget не виртуальный деструктор. С чего ты взял что он не виртуальный? У QObject - виртуальный деструктор - следовательно он виртуальный у всех его потомков, с том числе и QWidget.Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Red Devil от Июнь 29, 2008, 00:20 Да точно. Я забыл про QObject. Проверил и убедился, все правильно удаляется.
Но кстати вот еще проблема появилась. При удалении обьекта, в трейсе видно сообщение : QObject: Do not delete object, 'unnamed', during its event handler! Вот я где-то (на страничку эту уже не зайти, я её открыл с помощью кеша гугла) нашел обсуждение по его поводу. Цитировать Неоднократно замечены проблемы с перекрытием в обработке событий/сигналов и удаления объекта с этими обработчиками. На QT4.4 он начал предупреждать о подобном: QObject: Do not delete object, 'unnamed', during its event handler! Но не понятно другое, как это возможно в одном потоке и как это разруливать? Ситуация достаточно неочевидна и перестройкой пользовательского кода часто не лечится или лечится только путём потери функциональности. Например ситуация: - инспектор атрибутов генерирует сигнал на обновления виджета при потере фокуса; в процессе обновления удаляется вложенный виджет и вместо него создаётся новый; - в тоже время фокус теряется по причине выбора этого самого виджета (удаляемого), т.е. какие-то события пошли к нему; - в результате генерируется "QObject: Do not delete object, 'unnamed', during its event handler!" и происходит обрушение. Я не понимаю как такое может вообще происходить, разве в деструкторе не откидываются из очереди события к удаляемому виджету? Порылся в коде QT4.4 и меня насторожил вот этот участок кода в функции QCoreApplication::notifyInternal( ) файла qcoreapplication.cpp: bool returnValue; try { returnValue = notify(receiver, event); } catch(...) { --threadData->loopLevel; throw; } Получается при возникновении исключения оно передаётся на уровень выше, а флаг d->inEventHandler не очищается, что и является причиной указанного сообщения, а установка этого флага осуществляется только там. Не исключено, что не очищается ещё чего нибуть. ------- Comment #1 From Roman Savochenko 2008-05-26 21:45:26 ------- Created an attachment (id=2645) [details] Программа демонстрации проблемы Подготовил наглядный пример этой проблемы на основе примера из дистрибутива QT4.4 - basiclayouts. Для кнопки Button1 добавил eventFilter() c целью отлова потери фокуса. По результату потери фокуса удаляется кнопка Button2. Так вот, если сначала нажать кнопку Button1, а затем Button3, то кнопка Button2 корректно удалится, а вот если после Button1 нажать Button2, то программа упадёт по этой самой проблеме. ------- Comment #2 From Michael Shigorin 2008-05-31 02:43:48 ------- alterator-browser-qt - X11 Qt interface driver for alterator * Fri May 30 2008 Sergey V Turchin <zerg@altlinux> 2.9.83-alt1 - fix #15792 * Fri May 30 2008 Sergey V Turchin <zerg@altlinux> 2.9.82-alt1 - fix *listbox state-rows attribute - force return *multi*listbox current-rows and state-rows if empty list * Thu May 29 2008 Sergey V Turchin <zerg@altlinux> 2.9.81-alt1 ------- Comment #3 From Sergey V Turchin 2008-06-02 17:26:37 ------- Я не уверен, это бага Qt или нет, но можно использовать deleteLater ------- Comment #4 From Roman Savochenko 2008-06-02 17:56:29 ------- Это не всегда возможно. У меня был случай с QAbstractItemView::itemDelegate() Когда я создаю в качестве элемента редактирования комбобокс(редактируемый) и добавляю ему обработку события принятия выбора по выбору элемента. Так вот, если я редактирую содержимое этого комбобокса руками и нажимаю Enter, то приходит два события и он валится поскольку сама QT удалила этот элемент после первого события. Кроме того, на динамических интерфейсах, где элементы часто создаются и удаляются это неизбежно будет и проблему просто так не обойдёшь. ------- Comment #5 From Sergey V Turchin 2008-06-10 17:27:30 ------- Похоже, в Trolltech думают, что это фича http://trolltech.net/developer/task-tracker/index_html?method=entry&id=198093 http://trolltech.de/developer/task-tracker/index_html?method=entry&id=205903 ------- Comment #6 From Roman Savochenko 2008-06-24 00:14:37 ------- Если бы оно только писало и не падало. В приложенном примере нет моего кода, а оно устойчиво падает на банальной ситуации. Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Sergeich от Июнь 29, 2008, 00:33 Юзай QObject::deleteLater ()
Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Unnamed_Hero от Июнь 29, 2008, 10:51 Не знаю, насколько это корректно.... но я пока что поступаю таким образом -
Код: int index = tabWidget->currentIndex(); Код: setAttribute(Qt::WA_DeleteOnClose); всё удаляется... вроде :) Во всяком случае - видно, что деструкторы вызываются для всех объектов. Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Red Devil от Июнь 29, 2008, 12:02 Юзай QObject::deleteLater () Т.е. сам Qt удалит обьект, после того отработает цикл сообщений для него. И самому вручную delete использоваться получается не нужно. Но вот хотелось бы удостоверится что это действительно так. Название: Re: [Qt4] QTabWidget - кооректная чистка памяти Отправлено: Sergeich от Июнь 29, 2008, 13:44 Юзай QObject::deleteLater () Т.е. сам Qt удалит обьект, после того отработает цикл сообщений для него. И самому вручную delete использоваться получается не нужно. Но вот хотелось бы удостоверится что это действительно так. Код: void QObject::deleteLater() |