Управление памятью в Qt: учебник по адресной книге

Итак, я узнал, что Qt освобождает память всех дочерних объектов, когда родительский объект удаляется. Кроме того, обычно не нужно заботиться об управлении памятью для объектов, созданных в стеке (т.е. НЕ в качестве указателей).

Теперь, когда я сделал очень хороший руководство "Адресная книга", Я нашел это в части 5:

AddressBook::AddressBook(QWidget *parent) : QWidget(parent)
{
    dialog = new FindDialog;
}

Доступен полный исходный код: addressbook.h addressbook.cpp finddialog.h

Здесь dialog является частным членом AddressBook и является указателем на FindDialog. FindDialog наследует QDialog, но конструктору не передается this-Pointer (как показано выше). Явного деструктора не существует, delete dialog-вызова нет...

Кроме того, непрохождение this кажется преднамеренным:

Конструктор [FindDialog] определен для приема родительского QWidget, даже если диалоговое окно будет открыто как отдельное окно.

Не приведет ли это к утечке памяти? Или есть какой-то другой механизм, который молча удалит dialog и освободит его память?

Заранее благодарю за любую помощь!

Обновление: я разместил эту проблему на форумах qt-project.org и это скоро должно быть исправлено.


person Alex K    schedule 21.04.2014    source источник
comment
Хороший. Это почти наверняка утечка памяти, если только с макросом Q_OBJECT не происходит настоящего волшебства. Вы можете убедиться в этом с уверенностью, используя valgrind. Однако это не имеет значения, так как AddressBook длится все время жизни приложения. Тем не менее, в учебнике он должен был быть освобожден именно для того, чтобы не вызывать таких проблем, как у вас.   -  person Matt Phillips    schedule 21.04.2014
comment
@MattPhillips Но AddressBook длится только время жизни приложения, не влияет на dialog, не так ли? Было бы, если бы он был создан в стеке, но не в этом случае...   -  person Alex K    schedule 21.04.2014
comment
Дело в том, что экземпляр AddressBook уничтожается только тогда, когда приложение завершает работу, и в этот момент вся связанная с ним память, включая dialog, освобождается. Таким образом, утечки памяти удается избежать, но стилистически плохо и не масштабируемо.   -  person Matt Phillips    schedule 21.04.2014
comment
Насколько я понимаю, член должен быть объявлен следующим образом: FindDialog dialog. Тогда вам не нужно явно выделять или создавать его, и он не может протекать. Здесь вообще нет веской причины использовать указатель.   -  person Kuba hasn't forgotten Monica    schedule 21.04.2014
comment
Также возможно, что FindDialog освобождается при закрытии (модального?) диалогового окна...   -  person Massa    schedule 21.04.2014
comment
@Massa: Это, безусловно, возможно, но, возможно, должен быть комментарий на этот счет. Использование указателя по-прежнему является ненужным усложнением.   -  person Kuba hasn't forgotten Monica    schedule 21.04.2014
comment
Согласованный! И даже если диалог освободится, указатель будет болтаться...   -  person Massa    schedule 21.04.2014
comment
@Massa: не с QPointer, нет.   -  person lpapp    schedule 22.04.2014


Ответы (1)


Этому нет оправдания, и в конечном итоге у него больше проблем, чем вы только что подняли, а именно:

  • Это не управляется, как вы говорите.

  • Он не использует обычный синтаксис new Foo().

  • Это не делается в списке инициализаторов конструктора.

ОС, вероятно, освободит это после закрытия приложения, но тем не менее я всегда выступаю против таких проблем, особенно в примерах проектов. По моему мнению, подходящим решением было бы использовать либо объект стека вместо объекта кучи, либо QPointer.

См. следующий пост для получения подробной информации в случае последнего:

Как привести к сбою (почти) каждого приложения Qt/KDE и как это исправить

Об этом следует сообщать и фиксировать вверх по течению; хороший улов!

Я только что отправил Герриту изменение об этом здесь.

person lpapp    schedule 21.04.2014
comment
Спасибо за информацию и ссылку на запись в блоге.. очень интересно! Я только что опубликовал на форуме qt-project.org-Forum предложение исправить это. - person Alex K; 21.04.2014
comment
Дополнительное примечание о синтаксисе new Foo и new Foo(): поскольку Dialog является не-POD типом, они делают для него то же самое, но использование () по-прежнему будет хорошей практикой. Подробнее об этом, например, здесь. - person hyde; 22.04.2014
comment
@hyde: даже типы, не относящиеся к POD, попадают в отличие неинициализированных и инициализированных значений по умолчанию/значений с C++03 и дальше. Они также были неинициализированы в C++98, поэтому это также будет зависеть от стандартного варианта. Но, как написано в обновлении, теперь Герриту отправлено изменение, которое делает стек объектов, а не кучу. - person lpapp; 22.04.2014