crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

Гость_Гость_*
сообщение 24.9.2009, 8:25
Сообщение #1





Гости








    


Есть базовый виджет

class BaseFormWidget: public QWidget
{
    protected:
        QWebView* webView;
    public:
        BaseFormWidget(QWidget* parent = 0);
        ~BaseFormWidget();
};


Уничтожается так:

BaseFormWidget::~BaseFormWidget()
{
    delete webView;
}


От него наследуется другой виджет:

class frmServiceSelect: public BaseFormWidget
{
    Q_OBJECT

    private:
        std::vector<Button*> *serviceButtons;

        Button* _btnOk;
        Button* _btnBack;
        Button* _btnCancel;

        int _index;

    public:
        frmServiceSelect(QWidget *parent = 0, QDomNode *node = NULL, int id = 0);
        ~frmServiceSelect();

    public slots:
        void slotDestroy();
};


При нажатии на кнопку вызывается слот SlotDestroy, который вызывает деструктор:

frmServiceSelect::~frmServiceSelect()
{
    delete serviceButtons;
    delete _btnOk;
    delete _btnBack;
    delete _btnCancel;
}

void frmServiceSelect::slotDestroy()
{
    delete this;
}


При каждом цикле создания и удаления frmServiceSelect программа память освобождается не полностью. то 10-12 кб прибавляется к объему потребляемой оперативки, то 60-80... Как корректно подчистить память?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
3 страниц V   1 2 3 >  
Начать новую тему
Ответов (1 - 28)
BRE
  опции профиля:
сообщение 24.9.2009, 8:34
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(Гость @ 24.9.2009, 9:25) *
void frmServiceSelect::slotDestroy()
{
    delete this;
}

Не хорошо так удалять самого себя. Лучше воспользоваться методом QObject::deleteLater().

Утечки памяти лучше смотреть с помощью специальных средств.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 24.9.2009, 9:02
Сообщение #3


астарожна ынтжинэр
*****

Группа: Участник
Сообщений: 1404
Регистрация: 26.11.2008
Из: ТаганрогРодинаЧехова
Пользователь №: 435

Спасибо сказали: 113 раз(а)




Репутация:   23  


а почему ты в диструкторе уничтожаешь объекты?
BaseFormWidget::~BaseFormWidget() {     delete webView; }
frmServiceSelect::~frmServiceSelect() {     delete serviceButtons;     delete _btnOk;     delete _btnBack;     delete _btnCancel; }

у тебя что webView, serviceButtons, _btnOk, _btnBack, _btnCancel
не имеют parent`a ?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_Гость_*
сообщение 24.9.2009, 9:35
Сообщение #4





Гости








    


Паренты имеются, конечно же. А уничтожаю я так, для надежности :lol:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_Гость_*
сообщение 24.9.2009, 9:40
Сообщение #5





Гости








    


Скачал Deleaker - буду искать утечки
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 24.9.2009, 9:42
Сообщение #6


астарожна ынтжинэр
*****

Группа: Участник
Сообщений: 1404
Регистрация: 26.11.2008
Из: ТаганрогРодинаЧехова
Пользователь №: 435

Спасибо сказали: 113 раз(а)




Репутация:   23  


Цитата(Гость_Гость_* @ 24.9.2009, 10:35) *
Паренты имеются, конечно же. А уничтожаю я так, для надежности

я бы для надежности тогда уже писал
delete webView;
delete webView;

чтоб наверняка грохнуть!
:lol:
дока.
Цитата
Member Function Documentation
Q_INVOKABLE QObject::QObject ( QObject * parent = 0 )
Constructs an object with parent object parent.
The parent of an object may be viewed as the object's owner. For instance, a dialog box is the parent of the OK and Cancel buttons it contains.
The destructor of a parent object destroys all child objects.
Setting parent to 0 constructs an object with no parent. If the object is a widget, it will become a top-level window.
See also parent(), findChild(), and findChildren().

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_Гость_*
сообщение 24.9.2009, 9:49
Сообщение #7





Гости








    


Цитата(kwisp @ 24.9.2009, 9:42) *
я бы для надежности тогда уже писал
delete webView;
delete webView;

чтоб наверняка грохнуть!
:lol:


Я об этом уже тоже стал подумывать :lol:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 24.9.2009, 10:43
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Цитата(kwisp @ 24.9.2009, 10:42) *
delete webView;
delete webView;


Так надежности как раз не будет, так как программа просто упадет :unsure:

Вот если только так:

delete webView;
webView = 0;
delete webView;


А для указателей не на объекты на базе QObject'a можно использовать QSharedPointer.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 24.9.2009, 10:58
Сообщение #9


астарожна ынтжинэр
*****

Группа: Участник
Сообщений: 1404
Регистрация: 26.11.2008
Из: ТаганрогРодинаЧехова
Пользователь №: 435

Спасибо сказали: 113 раз(а)




Репутация:   23  


Цитата(SABROG @ 24.9.2009, 11:43) *
Цитата(kwisp @ 24.9.2009, 10:42) *
delete webView;
delete webView;
Так надежности как раз не будет, так как программа просто упадет :unsure:

это же шутка была!.

конечно упадет(в лучшем случае) а может и просто бед натворить по уничтожению других объектов.
а второй твой вариант тоже не зачем:)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 24.9.2009, 11:10
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(kwisp @ 24.9.2009, 11:58) *
а второй твой вариант тоже не зачем:)

Удаление нулевого указателя валидная операция. ;)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 24.9.2009, 13:24
Сообщение #11


астарожна ынтжинэр
*****

Группа: Участник
Сообщений: 1404
Регистрация: 26.11.2008
Из: ТаганрогРодинаЧехова
Пользователь №: 435

Спасибо сказали: 113 раз(а)




Репутация:   23  


Цитата(BRE @ 24.9.2009, 12:10) *
Удаление нулевого указателя валидная операция. ;)

пусть так.
а зачем это делать так явно?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 24.9.2009, 13:30
Сообщение #12


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(kwisp @ 24.9.2009, 17:24) *
а зачем это делать так явно?
Дык, для надёги. kwisp, ты разве не понял, что это уже шутки пошли ? :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 24.9.2009, 13:33
Сообщение #13


астарожна ынтжинэр
*****

Группа: Участник
Сообщений: 1404
Регистрация: 26.11.2008
Из: ТаганрогРодинаЧехова
Пользователь №: 435

Спасибо сказали: 113 раз(а)




Репутация:   23  


:lol:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 24.9.2009, 21:25
Сообщение #14


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Всегда считал, что удалять классы потомки от QObject через delete чревато. Только через QObject::deleteLater(). Ведь к объекту может обратиться event loop, а мы уже класс грохнули. Получим крах приложения. Поправьте, если я не прав.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 24.9.2009, 21:53
Сообщение #15


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(igor_bogomolov @ 24.9.2009, 22:25) *
Всегда считал, что удалять классы потомки от QObject через delete чревато. Только через QObject::deleteLater().

Вовсе не чревато.
Одновременно доступ к объекту может осуществляться только из разных потоков. Если этого нет, то любой объект можно спокойно удалять delete (даже если у него есть parent).

Цитата(igor_bogomolov @ 24.9.2009, 22:25) *
Ведь к объекту может обратиться event loop, а мы уже класс грохнули. Получим крах приложения. Поправьте, если я не прав.

Если сейчас выполняется твоя функция (в которой удаляется какой то объект), то это говорит о том, что процессор выполняет код этой функции, а не обрабатывает события или делает что-то еще. ;)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 24.9.2009, 22:16
Сообщение #16


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(BRE @ 25.9.2009, 1:53) *
Если сейчас выполняется твоя функция (в которой удаляется какой то объект), то это говорит о том, что процессор выполняет код этой функции, а не обрабатывает события или делает что-то еще.
а потом?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 24.9.2009, 22:38
Сообщение #17


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(Litkevich Yuriy @ 24.9.2009, 23:16) *
а потом?

А потом объекта уже не будет... Деструктор QObject уберет указатель на этот объект из списка parent (если он есть) и уничтожит его.

Сообщение отредактировал BRE - 24.9.2009, 22:41
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 24.9.2009, 23:52
Сообщение #18


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Сейчас глянул код деструктора - он давольно навороченый:
QObject::~QObject()
{
    Q_D(QObject);
    if (d->wasDeleted) {
#if defined(QT_DEBUG)
        qWarning("QObject: Double deletion detected");
#endif
        return;
    }
    d->wasDeleted = true;

    d->blockSig = 0; // unblock signals so we always emit destroyed()

    if (!d->isWidget) {
        // set all QPointers for this object to zero - note that
        // ~QWidget() does this for us, so we don't have to do it twice
        QObjectPrivate::clearGuards(this);
    }

    emit destroyed(this);
...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 25.9.2009, 9:14
Сообщение #19


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Ага, а потом делать рефакторинг приложения, если захочется добавить дополнительный поток. Лучше уж сразу deleteLater() использовать, если это не критично. Хотя я думаю, что в местах где скорость и память критичны - не используются QObject'ы.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 25.9.2009, 9:25
Сообщение #20


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(SABROG @ 25.9.2009, 10:14) *
Ага, а потом делать рефакторинг приложения, если захочется добавить дополнительный поток. Лучше уж сразу deleteLater() использовать, если это не критично. Хотя я думаю, что в местах где скорость и память критичны - не используются QObject'ы.

Не нужно удалять объект во всех методах класса, тогда в одном месте нужно будет заменить delete на deleteLater.
Если решил добавить поток, который будет работать с объектом из главного потока, там по любому нужно будет делать телодвижения для обеспечения корректного доступа к нему из нескольких потоков. ;)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 25.9.2009, 10:46
Сообщение #21


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Лучше, когда этих телодвижений меньше. Code less - create more.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 25.9.2009, 19:08
Сообщение #22


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Цитата(BRE @ 24.9.2009, 22:53) *
Если сейчас выполняется твоя функция (в которой удаляется какой то объект), то это говорит о том, что процессор выполняет код этой функции, а не обрабатывает события или делает что-то еще. ;)
Цитата(BRE @ 24.9.2009, 23:38) *
А потом объекта уже не будет... Деструктор QObject уберет указатель на этот объект из списка parent (если он есть) и уничтожит его.

Объект удалится, а сообщения для этого объекта почистятся в деструкторе QObject?
Помогите тогда разобрать в таком коде

MyLabel::MyLabel(QWidget *parent) : QLabel(parent)
{
    movie = new QMovie("post.gif", "gif", this);
    connect(movie, SIGNAL(frameChanged(int)), this, SLOT(myslot2()));
    movie->start();
}

void MyLabel::myslot2()
{
    qDebug("delete");
    delete movie;
//    movie->deleteLater();
}

В током виде приложение моментально падает, хотя из выше сказанного получается, что не должно. Если удалять через deleteLater, этого не произойдёт.

Хм...
Заменил QMovie на QTimer, затем на QPushButton - вылетов нет.
В чем проблема с QMovie?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 25.9.2009, 19:47
Сообщение #23


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Я чуть выше писал, что нельзя удалять объект из самого себя, для этого как раз подходит deleteLater.
А здесь, не явно, но именно это и происходит.
Из цикла обработки событий вызывается обработчик события таймера для объекта movie, он посылает сигнал frameChanged, это разворачивается в прямой вызов метода myslot2, из которого мы убиваем объект movie.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 25.9.2009, 20:02
Сообщение #24


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(BRE @ 25.9.2009, 23:47) *
это разворачивается в прямой вызов метода myslot2, из которого мы убиваем объект movie.
об этом я даже и не подумал
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 25.9.2009, 20:06
Сообщение #25


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Понятно.
Сколько интересно подобных объектов в Qt?
Вот и получается что удалять их через delete чревато, так как не известно как они реализованы, и к чему это приведёт. :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 25.9.2009, 20:20
Сообщение #26


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(igor_bogomolov @ 25.9.2009, 21:06) *
Вот и получается что удалять их через delete чревато, так как не известно как они реализованы, и к чему это приведёт. :)

Достаточно один раз разобраться и дальше не пытаться удалять объект из слота, который инициируется сигналом этого объекта. :)

IMHO. На самом деле если бы все было так плохо с delete, то Тролли уже давно перекрыли бы оператора delete для объекта QObject, что бы он имел такое же поведение как и deleteLater.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 25.9.2009, 20:28
Сообщение #27


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Я понимаю, что я уже придираюсь, и что это ошибки проектирования. Просто на примере с QMovie это не очевидно.
Теперь и я разобрался, буду иметь в виду :)

Сообщение отредактировал igor_bogomolov - 25.9.2009, 20:30
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 25.9.2009, 20:45
Сообщение #28


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Цитата(BRE @ 25.9.2009, 20:47) *
Из цикла обработки событий вызывается обработчик события таймера для объекта movie, он посылает сигнал frameChanged, это разворачивается в прямой вызов метода myslot2, из которого мы убиваем объект movie.


А можете мне объяснить подробней, я не разобрался? Вот мы запускаем таймер тут:

movie->start();


Он срабатывает при выходе из конструктора QLabel, когда заходим в цикл событий. При первом событии таймера movie удаляется, значит вместе с ним должен удалиться и таймер и краша быть не должно... В чем подводный камень?
---
А похоже понял. Внутренний вызов из метода QMovie метода myslot2 и возврат в уже не валидный объект.

Сообщение отредактировал SABROG - 25.9.2009, 20:53
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 25.9.2009, 21:05
Сообщение #29


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(SABROG @ 25.9.2009, 21:45) *
Он срабатывает при выходе из конструктора QLabel, когда заходим в цикл событий. При первом событии таймера movie удаляется, значит вместе с ним должен удалиться и таймер и краша быть не должно... В чем подводный камень?

DirectConnectin - подразумевает прямое связывание, т.е. грубо говоря emit signal() разворачивается в функцию:
void signal()
{
    obj->slot();    
}

Из eventloop'а активируется таймер объекта movie, мы попадаем в метод _q_loadNextFrame() объекта movie (!), из него идет прямой вызов метода slot2, в котором мы убиваем объект movie. После этого начинается откат из метода slot2, должны вернуться в _q_loadNextFrame объекта movie и продолжить выполнение этого метода. А movie - убит. Приплыли.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

3 страниц V   1 2 3 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0


RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 18.7.2025, 20:51