Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Удаление QObject: автоматически или нет, неясность с удалением объектов 
:(
    Опции темы
sustenuto
Дата 29.5.2011, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 28.4.2011

Репутация: нет
Всего: нет



Здравствуйте! Я первый раз работаю с QT и столкнулся с проблемой, решение которой не смог найти в документации. Суть сводиться к тому, что не ясно, кто должен удалять объект, производный от QObject: я или библиотека QT. Оказывается, что оба случая работают неправильно: если я создаю объект как статическую переменную (которая удаляется автоматически во время завершения программы), либо если я создаю его динамически, оператором new, и не удаляю совсем. В первом случае я получаю Segmentation Fault, во втором — утечку памяти. 

Мой класс описан примерно вот так:

Код

class LoadFileDialog : public QDialog , public Ui::LoadFileDialog {
    Q_OBJECT
public:
    LoadFileDialog(QWidget* parent=NULL);

    static bool showLoadFileWindow(const std::string& filename);

    void closeEvent (QCloseEvent * e);
private slots:
    void on_LoadFileButtons_clicked(QAbstractButton *);
    void update_data();
private:

    void paintEvent(QPaintEvent *event);
    void showFrame(Frame*);

public:
   ~LoadFileDialog() {
       std::cout<<"DIALOG DESTROYED!!!!"<<std::endl;
    }
};


Если объект LoadFileDialog сделать статической переменной, то при работе во время вызова его деструктора происходит Segmentation Fault. Если я объект не удаляю, то деструктор не вызывается вообще! Это я вижу, поскольку надписи "DIALOG DESTROYED!!!!" нет. Я предположил, что объект всё-таки уничтожается, но в силу того, что деструкторы QDialog и QWidget НЕ ВИРТУАЛЬНЫ (в отличие от деструктора QObject), вызывается неправильный деструктор. 

Друзья, как правильно делать?

PS. Кстати, если у меня ещё что-нибудь неправильно в классе, скажите плиз. Буду благодарен)

Это сообщение отредактировал(а) sustenuto - 29.5.2011, 19:43
PM MAIL   Вверх
borisbn
Дата 29.5.2011, 19:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 48
Всего: 135



Цитата(sustenuto @  29.5.2011,  19:26 Найти цитируемый пост)
деструкторы QDialog и QWidget НЕ ВИРТУАЛЬНЫ (в отличие от деструктора QObject)

на самом деле они виртуальные, т.к. при наследовании от QObject, где, как ты и сказал, деструктор виртуальный, их деструкторы (также, как и твой) становятся виртуальными.

где именно ты создаёшь объект LoadFileDialog статически, и где динамически ? Выложи весь код ( не жалей винград  smile ). А то так не очень понятно

Это сообщение отредактировал(а) borisbn - 29.5.2011, 19:31


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
sustenuto
Дата 29.5.2011, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 28.4.2011

Репутация: нет
Всего: нет



borisbn, спасибо за ответ!

Цитата(borisbn @  29.5.2011,  19:31 Найти цитируемый пост)
на самом деле они виртуальные, т.к. при наследовании от QObject, где, как ты и сказал, деструктор виртуальный, их деструкторы (также, как и твой) становятся виртуальными.


На самом деле, не совсем так. То есть если вызывается `delete dialog' где dialog имеет тип QDialog* (и фактически является объектом LoadFileDialog), то вызовется ~QDialog(). При этом `delete (QObject*)dialog' вызовет ~LoadFileDialog(). Я так понимаю.

Цитата(borisbn @  29.5.2011,  19:31 Найти цитируемый пост)
где именно ты создаёшь объект LoadFileDialog статически, и где динамически


Вроде бы максимально упростил код, ошибка сохраняется:

1. Статически. После закрытия окна получаю Segmentation Fault
Код

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    static LoadFileDialog dlg;
    dlg.show();

    return app.exec();
}


2. Динамически. Деструктор ~LoadFileDialog() никогда не вызывается
Код

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    LoadFileDialog* dlg=new LoadFileDialog;
    dlg->show();

    return app.exec();;
}


PM MAIL   Вверх
kosmonaFFFt
Дата 30.5.2011, 05:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 538
Регистрация: 14.4.2008
Где: Иннополис

Репутация: нет
Всего: 5



А попробуй создавать не статически, а просто
Код

LoadFileDialog dlg;




--------------------
user posted image
PM MAIL ICQ   Вверх
math64
Дата 30.5.2011, 07:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Когда ты создаёшь переменную так:
Код

    static LoadFileDialog dlg;

вместе с переменной dlg создаётся булевская переменная, по которой проверяется, создавался ли объект dlg. При первом вызове main() он будет создан.
Деструктор dlg будет вызван перед завершением программы, т.е. после выхода из main(), перед которым был вызван деструктор app, что и вызывает ошибку.
Нужно объявлять так:
Код

    QApplication app(argc, argv);
    LoadFileDialog dlg;

В этом случае деструкторы будут вызывааться при выходе из main() в порядке, обратном объявлению.
PM   Вверх
sustenuto
Дата 30.5.2011, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 28.4.2011

Репутация: нет
Всего: нет



Цитата(kosmonaFFFt @  30.5.2011,  05:40 Найти цитируемый пост)
А попробуй создавать не статически, а просто


Цитата(math64 @  30.5.2011,  07:42 Найти цитируемый пост)
Нужно объявлять так:


Ага, спасибо!
Только проблема в том, что объект надо создавать не в main, а в другой функции.
Можно было бы делать QApplication app статическим, но у него нету конструктора по умолчанию((( Так что и этот вариант тоже не прокатывает(

Решение проблемы я нашёл:
создавать dialog динамически и затем выполнять 
Код

dialog.setAttribute(Qt::WA_DeleteOnClose, true);

Тогда он удаляется корректно.

Всем спасибо!
PM MAIL   Вверх
math64
Дата 30.5.2011, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Цитата(sustenuto @  30.5.2011,  14:03 Найти цитируемый пост)
Только проблема в том, что объект надо создавать не в main, а в другой функции.
Можно было бы делать QApplication app статическим, но у него нету конструктора по умолчанию((( Так что и этот вариант тоже не прокатывает(

Создай класс, производный от QApplication и сделай LoadFileDialog dlg; или LoadFileDialog* dlg; полем в этом классе.
PM   Вверх
sustenuto
Дата 2.6.2011, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 28.4.2011

Репутация: нет
Всего: нет



Цитата(math64 @  30.5.2011,  14:35 Найти цитируемый пост)
Создай класс, производный от QApplication и сделай LoadFileDialog dlg; или LoadFileDialog* dlg; полем в этом классе. 


Здорово, отличное и красивое решение! Спасибо
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0759 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.