понедельник, 5 марта 2012 г.

Управление памятью в Qt

QГрабля#3


Известно, что немалая часть объектов Qt, с которыми приходится иметь дело, в той или иной мере являются контейнерами для других объектов, иногда это непосредственно так (например, для layout'ов), иногда вырождается в повсеместно существующую возможность назначить объекту некоторого родителя. Так или иначе, крайне часто вы передаете в метод (в т. ч. конструктор) объекта указатель на другой объект. Не таким уж странным в таком случае кажется решение создать объект на стеке, а в случае необходимости его куда-то передать просто использовать оператор взятия адреса.

Однако Qt в рамках своей юрисдикции сама управляет памятью - если вы удаляете объект, его деструктор автоматически удаляет всех своих детей и (вероятно) элементы, содержащиеся в нем. Естесственно, ей невозможно знать, был ли создан указатель операцией new, или он указывает на объект, для которого вовсе не освобождалась память в куче - при удалении вашему указателю сделают delete, что выльется в реальной практике в backtrace и memory dump на экран при завершении Qt-шного приложения, если этот указатель увел delete на стек. Однако если вы все объекты будете создавать в куче не заботясь об их удалении, то вы получите утечки памяти. Ясно, что позаботиться обо всех объектах также невозможно разумным образом - в частности, не удалить экземпляр QApplication (QCoreApplication) без странных костылей типа

int returnCode = app->exec();
delete app;
return returnCode;

которых вы никогда не увидите ни в одном руководстве по Qt. Ровно те же проблемы возникнут с объектом главного окна приложения.

Решение.

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


UPD


Несомненно более точно и тонко проблему освещает таки документация Qt

Комментариев нет:

Отправить комментарий