关于QT的内存申请和释放

关于QT的内存申请和释放

进入QT gui 设计的学习也有大半年年了,在做关于QT项目时遇到过关于内存释放错误的问题,曾经一度纠结过!以下是个人关于qt内存管理机制的总结:

 

首先看一个类:

       为了简单起见,我不完成任何功能,只做一个构造函数和一个析构函数。

 

代码 1.

class MyDialog : public QDialog

{

       Q_OBJECT

public:

       MyDialog();

       ~MyDialog();

private:

       QHBoxLayout *hLayout;

       QVBoxLayout *vLayout ;

       QPushButton *btn;

       QLineEdit *lineEdit ;

};

 

代码2.

 

MyDialog::MyDialog()

       :QDialog()

{

       btn = new QPushButton("Hello");

       lineEdit = new QLineEdit;

       hLayout = new QHBoxLayout;

       vLayout = new QVBoxLayout ;

      

       hLayout->addWidget(lineEdit);

       hLayout->addWidget(btn);

      

       vLayout->addLayout(hLayout1);

       setLayout(vLayout) ;

       connect(btn,SIGNAL(clicked()),this,SLOT(close()));

}

 

MyDialog::~MyDialog()

{

      

       delete btn ;

       delete lineEdit;

delete hLayout;

       delete vLayout ;

}

 

代码3.

 

int main(int argc , char ** argv)

{

       QApplication app (argc ,argv) ;

      

       MyDialog dlg ;

       dlg.show();

       return app.exec();

}

代码分析:

       从类的声明中,就不难看出,hLayout vLayout btn lineEdit;都是堆结构,就需要我没在 .cpp中实例化一下。

 

       从类的实现部分中,可以看出,好hLayout 布局是放在vLayout中的,按钮和编辑框是放在和Layout中的。

 

       现在看一下析构函数。

       经过C语言的学习我们知道,申请的堆空间如果不主动释放,系统不会帮你释放的,所以有new 就要有delete

       析构函数中,先释放按钮和标签 gui组件,然后释放不可见组件(布局),现在注意了,我们应该先释放好hLayout ,然后在释放Vlayout

       因为hLayout是建立在vLayout上的,如果释放了hLayout 的话,hLayout首先会与vLayout解除关系!

       如果在释放的时候,hLayout vLayout 的释放顺序颠倒过来,就会出现段错误,因为先 delete vLayout ,在delete hLayout 的时候,hLayout 将会与vLayout解除关系,但是此时vLayout已经不存在了,所以就会产生段错误。

 

       你些许会有疑问,那为什么btn lineEdit delete的先后顺序可以顺便呢。

 

这是因为 btn lineEdit 都是可见的Gui组件,delete gui组件时,不需要解除他与布局类的关系。所以顺序就可以随便写了。

 

总结:

       在使用堆结构定义对象的时候,特别是不可见组件,一定要从下往上释放(我说的是相对栈结构),也就是如果,layout1 包含layout2layout2 包含layout3 ,应该先delete layout3,在layout2,最后layout1 。这样就不容易出错了。

 

以上说的都是堆结构的,接下来总结一点,关于堆栈混用的。

现在看下面的类:

class MyDialog : public QDialog

{

       Q_OBJECT

public:

       MyDialog();

       ~MyDialog();

private:

       QHBoxLayout hLayout;

       QVBoxLayout vLayout ;

       QPushButton *btn;

       QLineEdit *lineEdit ;

};

这里我只是把 hLayout vlayout的结构改成了栈结构,而btn lineEdit还是原来的堆结构,构造函数在此就不写出了,逻辑和上面是一样的还是hLayout 放在vlayout中的。

下面是析构函数:

 

MyDialog::~MyDialog()

{

       delete btn ;

       delete lineEdit;

}

 

运行一下代码将会发现,出现了

*** glibc detected *** ./shiyan: double free or corruption (out): 0xbfa0a800 ***

======= Backtrace: =========

/lib/libc.so.6[0xc4bac1]

/lib/libc.so.6(cfree+0x90)[0xc4f0f0]

/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0x59d96f1]

/usr/lib/libstdc++.so.6(_ZdaPv+0x1d)[0x59d974d]

./shiyan(__gxx_personality_v0+0x357)[0x804a1e3]

./shiyan(__gxx_personality_v0+0x269)[0x804a0f5]

/lib/libc.so.6(__libc_start_main+0xe0)[0xbf8390]

./shiyan(_ZNK7QDialog8sizeHintEv+0x55)[0x8049fd1]

======= Memory map: ========

00110000-00111000 r-xp 00110000 00:00 0          [vdso]

00111000-009c5000 r-xp 00000000 fd:00 3441508    /root/qt/lib/libQtGui.so.4.4.0

009c5000-009e9000 rwxp 008b4000 fd:00 3441508    /root/qt/lib/libQtGui.so.4.4.0

009e9000-009ea000 rwxp 009e9000 00:00 0

009ea000-009ee000 r-xp 00000000 fd:00 1412324    /lib/libgthread-2.0.so.0.1400.2

009ee000-009ef000 rwxp 00003000 fd:00 1412324    /lib/libgthread-2.0.so.0.1400.2

009ef000-009f6000 r-xp 00000000 fd:00 1412323    /lib/librt-2.7.so

 

乱七八糟的东西,这是为什么呢?

这是因为,栈结构会被系统自动回收,在系统自动释放hLayoutLayout的时候,会把 btnlineEdit也释放掉,然后自己在写delete btndelete lineEdit的时候就会出现 double free,因为了把栈结构也释放掉了。

 

 

本文允许转载,但请注明出处。

                                                                                                    Write by douyuan888

                                                                                                                       2013/5/16

你可能感兴趣的:(关于QT的内存申请和释放)