Название: Удаление классов в Qt Отправлено: Evgeniya от Август 13, 2009, 14:35 Есть главная форма, из которой вызывается другая форма, а из нее третья и т.д. может быть
В документации по Qt написано, что нельзя самостоятельно удалять созданные экземпляры классов если они унаследованы от QObject, т.к. Qt сама заботится об освобождении памяти. Что же получается на практике, при создании диалогов им передается указатель на класс главного диалога и при закрытии дочерних диалогов их классы не удаляются, а удаляются только тогда когда будет закрыто главное окно. Но раз при каждом вызове создаётся новый экземпляр класса и не удаляется старый при закрытии дочерних диалогов происходит утечка памяти.... каким образом можно это все побороть? Название: Re: Удаление классов в Qt Отправлено: spectre71 от Август 13, 2009, 14:40 В документации по Qt написано, что нельзя самостоятельно удалять созданные экземпляры классов если они унаследованы от QObject, Такого в документации нет и не может быть!Название: Re: Удаление классов в Qt Отправлено: kuzulis от Август 13, 2009, 14:43 :)
есть 2 варианта: 1. Либо создавать новые формы и им в конструктор засовывать параметр parent от главной формы - и тогда не придется их удалять перед завершением приложения 2. Либо создавать новые формы ничо им не передавая - но удалять их "вручную" ЗЫ: вроде так , если не путаю Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 13, 2009, 14:46 Цитировать Такого в документации нет и не может быть! Значит я не правильно поняла (((Значит все-таки нужно удалять все динамически созданные объекты???? Я так понимаю, что если они все имеют родителя, то сами удалятся при закрытии главного окна...значит их можно удалять при закрытии определенного диалога,перегрузив, например метод closeEvent(QCloseEvent *event)?? я правильно понимаю??? Название: Re: Удаление классов в Qt Отправлено: spectre71 от Август 13, 2009, 15:02 Цитировать Такого в документации нет и не может быть! Значит я не правильно поняла (((Значит все-таки нужно удалять все динамически созданные объекты???? Я так понимаю, что если они все имеют родителя, то сами удалятся при закрытии главного окна...значит их можно удалять при закрытии определенного диалога,перегрузив, например метод closeEvent(QCloseEvent *event)?? я правильно понимаю??? 1) Если при создании не указан парент, то объект необходимо уничтожить самостоятельно 2) Если при создании указан парент, то объект удалиться при уничтожении парента, но и в этом этом случае объект можно удалить самостоятельно(до уничтожения парента). Просто при самостоятельном удалении он отвяжется от парента. Название: Re: Удаление классов в Qt Отправлено: lit-uriy от Август 13, 2009, 19:10 Цитировать о объект удалиться при уничтожении парента, но и в этом этом случае объект можно удалить самостоятельно(до уничтожения парента). Просто при самостоятельном удалении он отвяжется от парента. Что-то я в этом сильно сомневаюсьНазвание: Re: Удаление классов в Qt Отправлено: lit-uriy от Август 13, 2009, 19:11 При последующем удалении родителя, родитель неприятно вякнет
Название: Re: Удаление классов в Qt Отправлено: spectre71 от Август 13, 2009, 19:12 При последующем удалении родителя, родитель неприятно вякнет Ничего подобного.Название: Re: Удаление классов в Qt Отправлено: denka от Август 13, 2009, 19:18 Цитировать о объект удалиться при уничтожении парента, но и в этом этом случае объект можно удалить самостоятельно(до уничтожения парента). Просто при самостоятельном удалении он отвяжется от парента. Что-то я в этом сильно сомневаюсьЕлси заглянешь в исходники то убедишься что Spectre прав. Код: QObject::~QObject() Так как деструктор у QObject виртуальный то это справедливо для всей иерархии Название: Re: Удаление классов в Qt Отправлено: SABROG от Август 13, 2009, 21:36 Цитировать каким образом можно это все побороть? Нормальный и безопасный метод QObject::deleteLater(). Цитировать что нельзя самостоятельно удалять созданные экземпляры классов если они унаследованы от QObject А где такое написано? Название: Re: Удаление классов в Qt Отправлено: spectre71 от Август 13, 2009, 22:08 Нормальный и безопасный метод QObject::deleteLater(). Не надо запутывать..., это к поставленному вопросу не относится, здесь речь шла об обычном удалении объекта унаследованного от QObject.QObject::deleteLater() - необходим в определенных случаях в "мультипоточных" приложениях(корявинько написал :)) Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 13, 2009, 22:21 Все равно до конца не поняла....вот приведу часть кода
Код
Код
насколько правильно я освобождаю память?? А класс class Roszdrav в свою очередь вызывается в другом классе Название: Re: Удаление классов в Qt Отправлено: BlackTass от Август 13, 2009, 22:35 Ну я бы посоветовал после
delete l; поставить еще l = NULL; (это в методе add() ). И еще вопрос. Зачем вам одновременно #include "ls.h" и class LS; ? Вы либо второе удалите, либо первое в цппшник перенесите. А вообще хорошим тоном считается минимум инклюдов в хедерах. Большая часть их у вас просто не нужна, а нужна лишь уже в цппшнике. Название: Re: Удаление классов в Qt Отправлено: ритт от Август 14, 2009, 01:50 вообще, ужасно, конечно :)
но если без придирок, то память в конечном счёте всё-таки освободится (если приложение не свалится в closeEvent :) ) Название: Re: Удаление классов в Qt Отправлено: BlackTass от Август 14, 2009, 02:43 но если без придирок, то память в конечном счёте всё-таки освободится (если приложение не свалится в closeEvent :) ) по идее обязано свалиться в большинстве случаев Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 14, 2009, 05:58 вот и мне не очень нравится это :( поэтому и обратилась к вам за помощью...
вообще, ужасно, конечно :) ну как тогда лучше сделать???вообще ничего не освобождать или что?????но если без придирок, то память в конечном счёте всё-таки освободится (если приложение не свалится в closeEvent :) ) или может в классе задать атрибут Qt::WA_DeleteOnClose? Название: Re: Удаление классов в Qt Отправлено: BlackTass от Август 14, 2009, 08:04 Добавив присвоение l = NULL; вы избежите падений.
Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 14, 2009, 08:09 А если в классе задать атрибут Qt::WA_DeleteOnClose?
то может и не понадобится closeEvent??? Название: Re: Удаление классов в Qt Отправлено: ритт от Август 14, 2009, 08:10 Добавив присвоение l = NULL; вы избежите падений. а убрав "if(l!=NULL) delete l;" - тем-более :)Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 14, 2009, 08:23 значит мне вообще не нужно delete l???
просто этот класс может вызываться много раз и соответственно каждый раз будет выделяться память для l, пока не закроется главное приложение Roszdrav Название: Re: Удаление классов в Qt Отправлено: BRE от Август 14, 2009, 08:32 значит мне вообще не нужно delete l??? Удалять l в closeEvent не надо, ведь его удаление происходит в add.просто этот класс может вызываться много раз и соответственно каждый раз будет выделяться память для l, пока не закроется главное приложение Roszdrav Hint: А почему не создавать LS в методе add на стеке? И убрать указатель на l из класса? Код: void Roszdrav::add() { Название: Re: Удаление классов в Qt Отправлено: SABROG от Август 14, 2009, 08:37 Чтобы не мучаться с присвоением NULL для QObject'a можно использовать QPointer.
Но я бы сделал рефакторинг. Код
Указатели тут можно заменить на QSharedPointer. Если им присваивать новые указатели, то старый указатель автоматически удалиться, если его больше никто не использует. Точно также при уничтожении диалога указатели сами уничтожатся. Или можно использовать аггрегацию, но тут надо смотреть конкретно на реализацию класса LS. А вообще тут будет небольшая утечка памяти: Код Если диалог будет вызываться сотни раз, то созданные объекты QSelectionModel внутри класса QTableView никогда не удаляться. Поэтому лучше использовать существующую модель, а не создавать её каждый раз заново. Цитировать или может в классе задать атрибут Qt::WA_DeleteOnClose? Указатели внутри класса это не удалит.Цитировать Не надо запутывать..., это к поставленному вопросу не относится, здесь речь шла об обычном удалении объекта унаследованного от QObject. Оно всегда лучше чем обычный delete. Разве что, если в приложении вообще цикл событий не используется.QObject::deleteLater() - необходим в определенных случаях в "мультипоточных" приложениях(корявинько написал) Название: Re: Удаление классов в Qt Отправлено: BRE от Август 14, 2009, 08:42 А вообще тут будет небольшая утечка памяти: Почему? У модели указан parent, при удалении диалога будет удаляться модель.Код Если диалог будет вызываться сотни раз, то созданные объекты QSelectionModel внутри класса QTableView никогда не удаляться. Поэтому лучше использовать существующую модель, а не создавать её каждый раз заново. Оно всегда лучше чем обычный delete. Разве что, если в приложении вообще цикл событий не используется. Опять же, почему?Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 14, 2009, 08:56 Удалять l в closeEvent не надо, ведь его удаление происходит в add. А если мне l нужна как глобальная переменная....то как мне ее задать ??Hint: А почему не создавать LS в методе add на стеке? И убрать указатель на l из класса? Код: void Roszdrav::add() { Код не получается Название: Re: Удаление классов в Qt Отправлено: SABROG от Август 14, 2009, 09:04 Почему? У модели указан parent, при удалении диалога будет удаляться модель. Вообще да, что-то я подумал, что парентом будет вьюха. Тогда получается косяк, при закрытии диалога уничтожается модель на вьюхе главного окна. Но лучше взять за правило использовать одну модель, ситуации разные могут быть.Цитировать Опять же, почему? Хотя бы потому, что deleteLater() можно вызывать несколько раз на один и тот же объект, даже из разных потоков.А если мне l нужна как глобальная переменная....то как мне ее задать ?? Код не получается Давно ли вы дружите с C++? Код
Название: Re: Удаление классов в Qt Отправлено: BRE от Август 14, 2009, 09:11 Хотя бы потому, что deleteLater() можно вызывать несколько раз на один и тот же объект, даже из разных потоков. Тебе не кажется, что такой подход к написанию... ээээ... какбы не очень красив. ;)Если у меня есть желание и возможность грохнуть объект немедленно, то зачем мне ждать очередного входа в обработку очереди событий? В некоторых случаях использовать deleteLater удобно, в некоторых необходимо, но использовать его всегда, вместо delete IMHO не оправдано. :) Название: Re: Удаление классов в Qt Отправлено: BRE от Август 14, 2009, 09:13 А если мне l нужна как глобальная переменная....то как мне ее задать ?? А зачем это тебе?В методе add ты создаешь и убиваешь этот объект, т.е. живет он только в момент выполнения add. Название: Re: Удаление классов в Qt Отправлено: SABROG от Август 14, 2009, 09:17 Если у меня есть желание и возможность грохнуть объект немедленно, то зачем мне ждать очередного входа в обработку очереди событий? Чтобы синхронизировать работу потоков? Это не панацея. Если другого выбора нет, то можно. Название: Re: Удаление классов в Qt Отправлено: spectre71 от Август 14, 2009, 09:17 Хотя бы потому, что deleteLater() можно вызывать несколько раз на один и тот же объект, даже из разных потоков. Не может такого быть.Цитировать Note: It is safe to call this function more than once; when the first deferred deletion event is delivered, any pending events for the object are removed from the event queue. Только до тех пор пока объект не удален.Насколько я понял, можно сделать так MyObj* Obj; Код
А так будет ошибка Код
Название: Re: Удаление классов в Qt Отправлено: BRE от Август 14, 2009, 09:25 Чтобы синхронизировать работу потоков? Это не панацея. Если другого выбора нет, то можно. Можно, но не ...Цитировать Оно всегда лучше чем обычный delete. ;)Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 14, 2009, 09:28 А если мне l нужна как глобальная переменная....то как мне ее задать ?? А зачем это тебе?В методе add ты создаешь и убиваешь этот объект, т.е. живет он только в момент выполнения add. Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 14, 2009, 09:29 И еще ...У меня LS может вызываться еще и со вторым параметром (LS(QWidget *parent, QString mnnID))...
С С++ я возможно пока не очень дружу-только учуся, а с освобождением памяти так вообще тяжко,никогда этому внимания особого не уделяла...а тут у меня просто много классов и боюсь большой утечки памяти.... даж не знаю, можт все-таки указатели оставить LS *l...и когда она мне не нужна убивать ее???как вообще все-таки лучше сделать???? Название: Re: Удаление классов в Qt Отправлено: BRE от Август 14, 2009, 09:34 я просто потом использую метод класса LS в классе Roszdrav Т.е. ты хочешь один раз создать объект LS и использовать его в нескольких местах?Тогда, есть несколько вариантов: * Можно создавать объект LS в конструкторе Roszdrav. Плюс: простота. Минус: если методы объекта LS в данный момент не нужны, обхект все равно будет создан. * Можно использовать singleton. Плюс: объект LS будет создан при первой необходимости. Минус: дополнительные телодвижения в коде. :) Название: Re: Удаление классов в Qt Отправлено: BRE от Август 14, 2009, 09:35 И еще ...У меня LS может вызываться еще и со вторым параметром (LS(QWidget *parent, QString mnnID))... Код: void Roszdrav::add() Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 14, 2009, 09:36 А если я все-таки буду использовать указатель???то будут сплошные минусы??))))
Название: Re: Удаление классов в Qt Отправлено: BRE от Август 14, 2009, 09:37 А если я все-таки буду использовать указатель???то будут сплошные минусы??)))) Если будешь правильно использовать, то только плюсы. ;)Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 14, 2009, 09:40 А правильно - это значит удалять его, когда он мне не нужен?? через delete...
A объект QSqlQueryModel *ls мне не нужно будет удалять? Название: Re: Удаление классов в Qt Отправлено: BRE от Август 14, 2009, 10:32 А правильно - это значит удалять его, когда он мне не нужен?? через delete... Qt сильно расслабляет с механизмом удаления детей parent'ом.A объект QSqlQueryModel *ls мне не нужно будет удалять? Если ты указала parent при конструировании (в любом наследнике от QObject), то Qt гарантирует его уничтожение при уничтожении самого parent'а. До этого момента все эти объекты будут болтаться в памяти. Если тебе нужно уничтожить объект раньше (при жизни parent'а), то это можно сделать оператором delete. Например: Код Тогда, получиться что при жизни объекта Roszdrav сколько раз вызовется слот add, столько объектов LS и будет создано. Они все потом удаляться при разрушении объекта Roszdrav, но зачем они нам все нужны?! ;) Во всех остальных случаях удалять объекты нужно самой. Название: Re: Удаление классов в Qt Отправлено: SABROG от Август 14, 2009, 10:58 Не может такого быть. Докажи это.Цитировать А так будет ошибка Код
Не будет. processEvents() не обрабатывает deffered deletion. Должен быть полный возврат в основной цикл событий. Отдельно выделенный QEventLoop также не удаляет объекты. Удаление происходит только в том цикле событий в котором был вызвал deleteLater(). Цитата: BRE Можно, но не ... Какой смысл удалять QObject моментально? Сомневаюсь, что у тебя будет фабрика этих объектов, где количество их будет исчисляться тысячами. QObject - очень медленно создается. Исходя из этого у тебя будут единичные экземпляры, смысла удалять которые самому с целью экономии памяти нет. Думаю в 90% случаев при написании программ на Qt лучше использовать deleteLater() во избежание дальнейших проблем с поиском причин падений своего приложения.Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 14, 2009, 11:02 Просто Roszdrav также вызывается из другой формы...и при зарытии формы(нажатии на крестик) разве удалится QSqlQueryModel *ls..я так полагаю что нет, она удалится только если удалится форма ее вызывающая...а та в свою очередь может быть вызвана еще из одной формы))))
значит ls можно удалить при закрытии, т.е. в методе QCloseEvent, чтобы не было создано много объектов QSqlQueryModel.... Например: так лучше не стоит удалять объект LS самой???Код
Название: Re: Удаление классов в Qt Отправлено: BRE от Август 14, 2009, 11:20 Просто Roszdrav также вызывается из другой формы...и при зарытии формы(нажатии на крестик) разве удалится QSqlQueryModel *ls..я так полагаю что нет, она удалится только если удалится форма ее вызывающая...а та в свою очередь может быть вызвана еще из одной формы)))) Если у объекта будет установлен WA_DeleteOnClose, то объект разрушиться при закрытии и разрушит всех детей.значит ls можно удалить при закрытии, т.е. в методе QCloseEvent, чтобы не было создано много объектов QSqlQueryModel.... так лучше не стоит удалять объект LS самой??? Сто раз пользователь нажмет add, будет создано сто объектов LS, доступа к которым не будет.Это нужно? По мне - нет. Если ты подробней распишешь, что нужно в классе Roszdrav (для чего делать указатель на LS публичным, кто еще им может пользоваться и т.д.), то проще будет рекомендовать что-то конкретное. Название: Re: Удаление классов в Qt Отправлено: Evgeniya от Август 14, 2009, 14:08 Спасибо огромное,BRE...
Вроде разобралась!!!!!И даже обнаружила, что в некоторых местах действительно можно без выделения памяти обойтись, при вызове формы :D Название: Re: Удаление классов в Qt Отправлено: spectre71 от Август 14, 2009, 14:31 Не будет. processEvents() не обрабатывает deffered deletion. Должен быть полный возврат в основной цикл событий. Отдельно выделенный QEventLoop также не удаляет объекты. Удаление происходит только в том цикле событий в котором был вызвал deleteLater(). Если и так. То другой вариант, вторично вызвать Obj->deleteLater(); по таймеру. :) Тут уж точно глюкнет. И это не единственный вариант.Название: Re: Удаление классов в Qt Отправлено: SABROG от Август 14, 2009, 15:18 Не будет. processEvents() не обрабатывает deffered deletion. Должен быть полный возврат в основной цикл событий. Отдельно выделенный QEventLoop также не удаляет объекты. Удаление происходит только в том цикле событий в котором был вызвал deleteLater(). Если и так. То другой вариант, вторично вызвать Obj->deleteLater(); по таймеру. :) Тут уж точно глюкнет. И это не единственный вариант.Понятно, что глюканет, тут речь о другой ситуации - многопоточности. Название: Re: Удаление классов в Qt Отправлено: Igors от Август 17, 2009, 19:14 насколько правильно я освобождаю память?? А класс class Roszdrav в свою очередь вызывается в другом классе 1) Почему бы просто не написать LS theL(this); Т.е. просто локальная переменная вместо указателя. Деструктор вызовется автоматически при выходе из функции. 2) Если деструктор все-таки нужен - его объявление должно быть virtual. Edit: пардон, не увидел страниц 2 и 3 :) Ответил что уже отвечено Название: Re: Удаление классов в Qt Отправлено: denka от Август 17, 2009, 19:21 насколько правильно я освобождаю память?? А класс class Roszdrav в свою очередь вызывается в другом классе 1) Почему бы просто не написать LS theL(this); Т.е. просто локальная переменная вместо указателя. Деструктор вызовется автоматически при выходе из функции. 2) Если деструктор все-таки нужен - его объявление должно быть virtual. Обоснуй пункт 2 Зы Как уже писалось выше классы унаследованые от QObject уже с виртуальным деструктором Название: Re: Удаление классов в Qt Отправлено: Igors от Август 19, 2009, 17:20 Обоснуй пункт 2 Но этого никак не видно без лазания по h файлам :) И чем держать это в памяти, для меня лучше написать virtual и быть уверенным что любое delete (хоть из parent хоть как) такой деструктор позовет. Зы Как уже писалось выше классы унаследованые от QObject уже с виртуальным деструктором Название: Re: Удаление классов в Qt Отправлено: denka от Август 19, 2009, 18:50 Виртаульный деструктор нужен лишь в случае иерархии классов, иначе виртуальность лишь уменьшение производительности
|