2017年(18)
分类: 嵌入式
2017-04-18 15:42:42
摘录其中一文片段如下:
QT有一套回收内存的机制,主要的规则如下:
1、所有继承自QOBJECT类的类,如果在new的时候指定了父亲,那么它的清理时在父亲被delete的时候delete的,所以如果一个程序中,所有的QOBJECT类都指定了父亲,那么他们是会一级级的在最上面的父亲清理时被清理,而不用自己清理;(注:这里是在new出来对象的时候,这样依靠QObject释放的内存一点问题没有,如果以下这种起情况,那么程序会崩溃
1
2
3
|
QObject derver;
QObject base;
derver.setParent(&base);
|
儿子和父亲都是栈空间上,释放内存时候,先释放父亲,释放父亲空间的时候,已经把儿子的内存释放了,当释放儿子的内存的是否,会出现内存错误,因为儿子被释放了两次)
2、程序通常最上层会有一个根的QOBJECT,就是放在setCentralWidget()中的那个QOBJECT,这个QOBJECT在 new的时候不必指定它的父亲,因为这个语句将设定它的父亲为总的QAPPLICATION,当整个QAPPLICATION没有时它就自动清理,所以也无需清理。
3、如果我们自己释放掉设置QObject为自己父亲的类对象,那个指向的父亲的QObject会从自己的儿子列表中把这个儿子删除掉,就不会出现儿子的内存会被释放两次,如果我们要删除有这种关系的QObject类的话,正常情况,这样它会将这个儿子移出它的列表,并且重新构建显示内容,但是直接这样做时有风险的!
4、当一个QOBJECT正在接收事件队列时如果中途被你DELETE掉了,就会出现问题了,所以QT中建议大家不要直接DELETE掉一个 QOBJECT,如果一定要这样做,要使用QOBJECT的deleteLater()函数,它会让所有事件都发送完一切处理好后马上清除这片内存,而且就算调用多次的deletelater也不会有问题。
5、QT不建议在一个QOBJECT 的父亲的范围之外持有对这个QOBJECT的指针,因为如果这样外面的指针很可能不会察觉这个QOBJECT被释放,会出现错误,如果一定要这样,就要记住你在哪这样做了,然后抓住那个被你违规使用的QOBJECT的destroyed()信号,当它没有时赶快置零你的外部指针。当然我认为这样做是及其麻烦也不符合高效率编程规范的,所以如果要这样在外部持有QOBJECT的指针,建议使用引用或者用智能指针,如QT就提供了智能指针针对这些情况,见最后一条。
6、QT中的智能指针封装为QPointer类,所有QOBJECT的子类都可以用这个智能指针来包装,很多用法与普通指针一样
(某些内存泄露的检测工具会认为QT的程序因为这种方式存在内存泄露,大家不必理会)
还有一个内存泄漏的问题:
class ReadoutDisplay : public QWidget
{
Q_OBJECT
public:
……………….
private:
QGridLayout *m_Gridlayout;
int m_no_of_rows;
int m_no_of_col;
};
ReadoutDisplay::ReadoutDisplay(QWidget *parent, QString type) :
QWidget(parent){
m_type = type;
m_Gridlayout = new QGridLayout;
泄漏的原因是这里在类中声明的了一个类对象指针,在成员函数中分配了空间,但是没有在成员函数中释放,解决的办法是在析构函数中检查释放:
ReadoutDisplay::~ReadoutDisplay()
{
if(m_Gridlayout)
{
delete m_Gridlayout;
m_Gridlayout = NULL; // once we delete a pointer, it was highly recommended
}
}