[완료] Qt에서의 메모리 할당/해제 메커니즘이 궁금합니다.
글쓴이: comkid / 작성시간: 일, 2008/05/04 - 5:01오후
질문이 좀 거창해졌는데요..
다른 것이 아니고 Qt Tutorial 4 - Let There Be Widgets 항목에 보면
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
setFixedSize(200, 120);
QPushButton *quit = new QPushButton(tr("Quit"), this);
quit->setGeometry(62, 40, 75, 30);
quit->setFont(QFont("Times", 18, QFont::Bold));
connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
}에서 quit에 대해 아래와 같이 설명이 나오는데요..
Quote:
Note that quit is a local variable in the constructor. MyWidget does not keep track of it; Qt does, and will automatically delete it when the MyWidget object is deleted. This is why MyWidget doesn't need a destructor. (On the other hand, there is no harm in deleting a child when you choose to. The child will automatically tell Qt about its imminent death.)
튜토리얼 볼 때는 스마트 포인터를 썼나 하고 그냥 그런가 보다 하고 넘어갔었는데요. 막상 제가 클래스 정의해서 하려니 정말 명시적으로 delete를 해주지 않아도 되는 것인가 하는 생각이 들어서요.
Qt의 메모리 할당/해제 메커니즘을 알면 답이 보일 것도 같은데 책이랑 문서랑도 봐도 (제가 키워드를 제대로 못 골라서인지) 제가 궁금한 부분에 대해서 알려주는 내용은 없어서요.
이런 고민을 하고 있는 이유는
QMainWindow를 상속받은 클래스를 정의하고 그 안에 제가 정의한 클래스(QObject를 상속받지 않은 C++ 클래스)에 대한 포인터를 멤버로 갖고 생성자에서 할당을 하려고 하는데 이런 경우에도 소멸자에 해제하는 루틴을 따로 만들지 않아도 알아서 해제가 되는 것인지..가 궁금해서요. 느낌 상(?) 그냥은 안될 것 같은데요. QObject를 상속한 클래스에 대해서만 자동으로 해제가 이루어지지 않나 막연히 추측하고 있는데..
저의 이런 궁금증을 속~ 시원하게 긁어 주실 분 안계신가요?
Forums:


생각하신대로 일단은
생각하신대로 일단은 QObject를 상속하지 않은 클래스는 자동 해제 대상에서 제외됩니다.
하지만 QObject를 상속받았으니까 무조건 자동 해제되는 건 아닙니다.
QObject를 상속받고, 부모 객체에 등록된 자식 객체가, 부모객체가 삭제될때 자동으로 삭제되는 것입니다.
여기서 말하는 부모는 상속관계에 있는 base 클래스와 derived 클래스를 말하는게 아니라 생성자에서 parent로 넘어간 포인터를 말합니다.
조금 더 자세한건 다음 글의 끝 부분에 적혀있습니다.
http://xylosper.net/112
디버깅 돌려보시면 소멸자에서 자식들을 해제하는 과정을 보실수도 있습니다.
추가 질문이 있는데요..
Colding Mice라는 샘플을 보면 QGraphicsItem에 대한 파생 클래스인 Mouse는 new로 생성할 때 따로 parent를 설정하지 않는데요. 이런 경우에는 어떤 식으로 해제가 되는 건가요?
QGraphicsScene scene; scene.setSceneRect(-300, -300, 600, 600); scene.setItemIndexMethod(QGraphicsScene::NoIndex); for (int i = 0; i < MouseCount; ++i) { Mouse *mouse = new Mouse; mouse->setPos(::sin((i * 6.28) / MouseCount) * 200, ::cos((i * 6.28) / MouseCount) * 200); scene.addItem(mouse); }예제 간혹 보다보면 new로 동적할당 하면서도 parent를 넘기지 않는 애들이 있는데 이런 경우는 그 객체가 add되는 녀석이 해제를 하는게 아닐까 하고 넘어갔는데 실제로도 그러한지는 잘 모르겠어서요.
그리고 제가 Qt는 처음 써봐서 mignw-g++, qt, vim으로 MS 윈도우 환경에서 프로그래밍 하고 있는데요.
어떤 식으로 디버깅 해볼 수 있는지 참고 할 수 있는 자료도 알려주시면 감사하겠습니다..^^;
Have a good day!
이런 경우는 좀
이런 경우는 좀 특별한 경우입니다.
assistant를 보시면 알겠지만 애시당초 QGraphicsItem는 QObject를 상속받은 클래스가 아닙니다.
특별하게 설계된 아이템 클래스들은 add된 곳에서 삭제됩니다.
말씀하신대로 이경우는 각 아이템은 그 아이템이 등록된 부모 아이템이나 최종적으로는 scene이 삭제할 책임을 가집니다.
이외에도 QListWidget/QTableWidget/QTreeWidget과 그 item클래스들도 마찬가지로 최종적으로 각 widget에 의해서 할당된 item들이 해제됩니다.
이것들을 해제하는 알고리즘은 어려운게 아닙니다.
예를 들어 QGraphicsScene의 소멸자는 다음과 같이 간단합니다.
QGraphicsScene::~QGraphicsScene() { Q_D(QGraphicsScene); for (int i = 0; i < d->newItems.size(); ++i) { if (QGraphicsItem *item = d->newItems[i]) { d->newItems[i] = 0; d->removeFromIndex(item); item->d_func()->scene = 0; delete item; } } for (int i = 0; i < d->allItems.size(); ++i) { if (QGraphicsItem *item = d->allItems[i]) { if (!d->removedItems.contains(item)) { d->allItems[i] = 0; d->removeFromIndex(item); item->d_func()->scene = 0; delete item; } } } }보통은 문서에 나와있습니다만, 실제로 삭제되는지 궁금하다면 디버깅을 돌려보거나 위와같이 소스코드를 직접 찾아보면 되겠죠.
디버깅에 대해선, 전 항상 kdevelop이나 eclipse같은 IDE로밖에 안해봐서 직접 gdb등을 이용한 디버깅은 잘 모르겠네요.
Qt라고 특별히 다를 건 없는 것 같습니다. 중단점 찍고 스택보거나 출력함수로 직접 출력해보거나...
참고로 직접 출력할때는 qDebug()를 이용하면 간편합니다.
답변 감사합니다.
xylosper님 블로그도 갔었는데.. 링크해주신.. 부분은 왜 못 봤던 건지-_-;;
parent로 this가 넘어가는 걸 주의깊게 보질 않았었네요..
알려주신 내용으로 궁금한 부분은 해결되었습니다. 빠른 답변 감사합니다 :)
Have a good day!
댓글 달기