Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt GUI _ Гарантия на деструктор.

Автор: call_me_Frank 21.11.2013, 17:26

Господа, есть вопрос. Насколько можно быть уверенным в том, что при закрытии приложения (не аварийном) будут выполнены все команды в деструкторе объекта?

Пример:

int main(int argc, char *argv[]){
    //

    QApplication a(argc, argv);
    //QApplication::setQuitOnLastWindowClosed(false);

    // GUI
    MainWindow w;
    w.show();

    Mainy *my = new Mainy(&a);

    return a.exec();
}


Mainy - класс-наследник от QObject, его деструктор:
Mainy::~Mainy(){
    //

    qDebug() << "~Mainy() ";
}


сообщение выводится в 50% случаев закрытия.

я не знаю, как работает дебаг, но у меня из-за этого серьезные опасения насчет того, что половина инструкций внутри деструктора может просто не выполниться...

Автор: Iron Bug 21.11.2013, 18:56

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

Автор: call_me_Frank 22.11.2013, 7:26

Хорошо, деструктор вызывается в 100% случаев без исключений. Но вывод функции qDebug() случается далеко не каждый раз. Почему? Я предполагаю, что вызвав qDebug(), программа в итоге завершается быстрее, чем производится сам вывод. Все бы ничего - черт с ним с дебагом, но меня беспокоит то, что вероятно есть и другие функции, которые будут вести себя подобным же образом. И как в таком случае проследить 100-процентное выполнение всех до полного завершения? Работать в режиме отладки возможности нет, т.к. использую либы, которые этот режим не поддерживают и портят всю малину.

Насчет delete. В данном примере я рассчитываю на то, что об этом позаботится родитель моего объекта (&a). Или я не прав? В таком случае, где же разместить delete my, чтобы он вызывался при закрытии программы? Делать для этого отдельный класс с соотв. слотом неохота...

Автор: Iron Bug 22.11.2013, 8:28

Цитата(call_me_Frank @ 22.11.2013, 10:26) *
В данном примере я рассчитываю на то, что об этом позаботится родитель моего объекта (&a).

динамическое выделение памяти НЕ вызывает деструкторы в нормальном случае. нужен явный вызов delete. если его не было, система будет удалять объект при очистке памяти приложения. естественно, на тот момент самой программы уже не будет.

если нет понятного места, где нужно удаление объекта, используются автоматические указатели.

Автор: Litkevich Yuriy 23.11.2013, 15:50

Цитата(Iron Bug @ 21.11.2013, 20:56) *
а у тебя ещё нет вызова delete. раз ты его создал (new), то должен быть и delete.
там наследование от QObject, а он (и его потомки) сами удаляют своих детей. Под детьми понимаются объекты созданные с указанием родителя, конструктор QObject:
QObject ( QObject * parent = 0 )

Пример в коде:
SomeClass *parent = new SomeClass(0); // 0 - для примера, что явно нет родителя
SomeClass *obj = new SomeClass(parent); // есть родитель

В таком коде obj явно удалять не нужно, это сделает деструктор parent-а.
А вот parent удалять нужно самому.

Обычно код на Qt выглядит так:

int main (...)
{
    SomeClass parent(); // Создан на стеке, чтобы руками не удалять

}

// ....

SomeClass::SomeClass(...)
{
    OtherClass *object = new OtherClass(this); // передан в качестве родителя экземпляр ЭТОГО класса
}


Цитата(call_me_Frank @ 21.11.2013, 19:26) *
сообщение выводится в 50% случаев закрытия.

Цитата(Iron Bug @ 21.11.2013, 20:56) *
деструктор выполняется всегда, когда объект уничтожается. при выходе за область видимости объект уничтожается. тут нет никаких вариантов и неясностей.
по моей практике, если выходим за область видимости при выходе из функции main, то объекты непосредственно созданные в ней, действительно могут убиваться каким-то иным способом и деструктор не вызывается (и довольно нестабильно это).
При этом код может не использовать ни каких библиотек (например, Qt).

С чем это связано я до сих пор не знаю.

Автор: Iron Bug 23.11.2013, 16:57

Цитата(Litkevich Yuriy @ 23.11.2013, 18:50) *
по моей практике, если выходим за область видимости при выходе из функции main, то объекты непосредственно созданные в ней, действительно могут убиваться каким-то иным способом и деструктор не вызывается (и довольно нестабильно это).
При этом код может не использовать ни каких библиотек (например, Qt).

С чем это связано я до сих пор не знаю.

ну тогда всё понятно: QApplication удаляется уже после выхода из main. соответственно, на этом этапе ничего от программы не остаётся. обращения к ресурсам программы ошибочны. а если это срабатывает, то только потому, что система ещё не успела затереть память.

Автор: Litkevich Yuriy 23.11.2013, 20:08

К стати, нашёл у себя во фрагментах кода (заготовочках), такую штуку:

int main (...)
{
    int res = 0;
    {
        QApplication a(argc, argv);
        ...
        res = a.exec();
     }
     return res;
}
т.е. работать должно так: как только Qt приложение заканчивает работать, то QApplication::exec(), возвращает управление (цикл обработки событий прерывается). Затем происходит выход из области видимости (фигурные скобки), но функция main ещё не завершилась.
Этот трюк позволяет отработать всем нужным/полезным деструкторам до завершения функции main.

Автор: Iron Bug 24.11.2013, 9:33

Цитата(Litkevich Yuriy @ 23.11.2013, 23:08) *
К стати, нашёл у себя во фрагментах кода (заготовочках), такую штуку:

да, это, безусловно, будет работать. область видимости закрывается раньше, чем завершается main и уничтожаются ресурсы программы.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)