• 9927阅读
  • 15回复

[提问]这个多线程例子,有没有内存泄露?为什么内存不断升高? [复制链接]

上一主题 下一主题
离线tthheedhz
 
只看楼主 倒序阅读 楼主  发表于: 2012-05-24

Thread类:
class Thread:public QThread
{
    Q_OBJECT
protected:
    void run();
};

void Thread::run()
{
    while(true)
    {
        msleep(100);
        QThread* t=new QThread();
        t->start();
    }
}

main.cpp如下:

int main(int argc,char*argv[])
{
    QApplication app(argc,argv);
    Thread t;
    t.start();
    return app.exec();
}

离线tthheedhz
只看该作者 1楼 发表于: 2012-05-24
我一直认为,QThread类,在run函数结束后,是会自动销毁、释放内存的,是吧?
离线tthheedhz
只看该作者 2楼 发表于: 2012-05-24
我开始以为,是这两句代码,产生了内存泄露:

        QThread* t=new QThread();
        t->start();

我本以为,new之后,没有delete,应该是会产生,内存泄露的。

但后来,发现,QThread好象在run函数结束后,是会自动销毁、释放内存的。

于是,我立即糊涂了。不知道问题出在哪里了。
离线roywillow

只看该作者 3楼 发表于: 2012-05-24
你确定……你的这个run()会执行完?
我记得QThread类的run()函数曾经发生过一次改变,现在run()中默认会执行exec(),除非你将run()重写
也就是说,那些new的QThread,大概会在exec()不断进行事件循环,它的run()也就不会结束的
另外我也不是很清楚在run()中new的QObject如果没有指定parent会不会自动被销毁
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线tthheedhz
只看该作者 4楼 发表于: 2012-05-24
引用第3楼roywillow于2012-05-24 16:59发表的  :
你确定……你的这个run()会执行完?
另外我也不是很清楚在run()中new的QObject如果没有指定parent会不会自动被销毁

你指的是QThread的run(),还是Thread的run()?
离线roywillow

只看该作者 5楼 发表于: 2012-05-24
回 4楼(tthheedhz) 的帖子
both
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线tthheedhz
只看该作者 6楼 发表于: 2012-05-24
Re:回 4楼(tthheedhz) 的帖子
引用第5楼roywillow于2012-05-24 17:05发表的 回 4楼(tthheedhz) 的帖子 :
both

Thread的run,是肯定不会完毕的,因为里面是while(true)。


QThread的run,我不确定。

不过我后来改写了程序,相信这样的话,肯定是正确代码:

但内存依然升高,不过上升的速率,慢了下来。









Thread类:
class Thread1:public QThread
{
    Q_OBJECT
protected:
    void run();
};
class Thread2:public QThread
{
    Q_OBJECT
protected:
    void run();
};

void Thread1::run()
{
    while(true)
    {
        msleep(100);
        Thread2* t=new Thread2();
        t->start();
    }
}
int c=0;
void Thread2::run()
{
   c++;
  qDebug()<<c<<endl;
}

main.cpp如下:

int main(int argc,char*argv[])
{
    QApplication app(argc,argv);
    Thread1 t;
    t.start();
    return app.exec();
}

离线roywillow

只看该作者 7楼 发表于: 2012-05-24
那么这个代码你看到Thread2的run()的结束了吗?
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线tthheedhz
只看该作者 8楼 发表于: 2012-05-24
引用第7楼roywillow于2012-05-24 17:23发表的  :
那么这个代码你看到Thread2的run()的结束了吗?

怎么看呢?

qDebug()都执行了、输出了。run还能不结束?
离线tthheedhz
只看该作者 9楼 发表于: 2012-05-24
引用第7楼roywillow于2012-05-24 17:23发表的  :
那么这个代码你看到Thread2的run()的结束了吗?

有没有什么想法?

我的程序,当有请求的时候,就需要开一个线程,执行一些任务,任务完毕后线程自动退出。

现在还不到一天,整个程序的内存就上升到几百MB了。

内存泄露非常严重啊。
离线roywillow

只看该作者 10楼 发表于: 2012-05-24
回 8楼(tthheedhz) 的帖子
你可以在Thread2的析构函数中qDebug()一下看看
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线tthheedhz
只看该作者 11楼 发表于: 2012-05-25
Re:回 8楼(tthheedhz) 的帖子
引用第10楼roywillow于2012-05-24 23:53发表的 回 8楼(tthheedhz) 的帖子 :
你可以在Thread2的析构函数中qDebug()一下看看

在Thread2的析构函数中添加qDebug()了,没有反应,没有任何输出。

就是说,没有被析构了。

到底,该如何正确退出一个QThread?

离线tthheedhz
只看该作者 12楼 发表于: 2012-05-25
Re:回 8楼(tthheedhz) 的帖子
引用第10楼roywillow于2012-05-24 23:53发表的 回 8楼(tthheedhz) 的帖子 :
你可以在Thread2的析构函数中qDebug()一下看看

我添加了下面这行代码,析构函数还是没有被调用。

connect(t, SIGNAL(finished()), t, SLOT(deleteLater()));
离线roywillow

只看该作者 13楼 发表于: 2012-05-25
回 12楼(tthheedhz) 的帖子

专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线tthheedhz
只看该作者 14楼 发表于: 2012-05-25
Re:回 12楼(tthheedhz) 的帖子
引用第13楼roywillow于2012-05-25 08:02发表的 回 12楼(tthheedhz) 的帖子 :
[表情]


帮忙想想吧。

我把while循环里的内容改成下面后,就再也没有内存泄露了:

        Thread2* t=new Thread2();
        t->start();
        t->wait();
        delete t;

而且,的确看到Thread2的析构函数也被调用了。

但问题的关键是,我的程序,监听线程是不能进入wait()的。监听线程,只是作为监听、开启线程而用。

监听线程,是不允许进入阻塞状态的,因为它必须不停地监听。

有什么办法,可以改造一下?





离线tthheedhz
只看该作者 15楼 发表于: 2012-05-25
Re:回 12楼(tthheedhz) 的帖子
引用第13楼roywillow于2012-05-25 08:02发表的 回 12楼(tthheedhz) 的帖子 :
[表情]


我发现:

这个没有内存泄露:
        Thread2* t=new Thread2();
        t->start();
        t->wait();
        delete t;

这个则存在内存泄露:
        Thread2* t=new Thread2();
        t->start();
        t->wait();
        t->deleteLater();
快速回复
限100 字节
 
上一个 下一个