您的位置:首页 > 编程语言 > Qt开发

关于QT的内存申请和释放

2013-07-01 10:28 239 查看
关于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
包含layout2,layout2
包含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

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

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

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

Write by
:douyuan888

2013/5/16
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: