查看完整版本: [-- 线程内使用emit(),内存泄漏十分严重,哪里出了问题?有源代码 --]

QTCN开发网 -> Qt基础编程 -> 线程内使用emit(),内存泄漏十分严重,哪里出了问题?有源代码 [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

勤为径也 2018-01-01 22:35

线程内使用emit(),内存泄漏十分严重,哪里出了问题?有源代码

一个十分简单的QT程序,线程启动后内存泄漏十分严重。
QT新手请高手指点。谢谢!!
  1. //main.cpp
    #include "test_thread.h"
    #include <QtWidgets/QApplication>

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Test_Thread w;
        w.show();
        return a.exec();
    }

  1. //test_thread.h
    #ifndef TEST_THREAD_H
    #define TEST_THREAD_H

    #include <QtWidgets/QMainWindow>
    #include "ui_test_thread.h"
    #include <QtWidgets/QTextBrowser>
    #include <QtWidgets/QWidget>
    #include <QtWidgets/QLayout>
    #include<QtCore/QThread>  
    #include "mythread.h"

    class Test_Thread : public QMainWindow
    {
        Q_OBJECT

    public:
        Test_Thread(QWidget *parent = 0);
        ~Test_Thread();
        Ui::Test_ThreadClass ui;
        QWidget *widget;
        QVBoxLayout *layout;
        QTextBrowser *textBrowser;

    private:
        void creat_Label();
        QThread * t2 = new QThread();
        MyObject * obj1 = new MyObject();

    };

    #endif // TEST_THREAD_H

  1. //test_thread.cpp
    #include "test_thread.h"
    #include <QtCore/QDebug>
    Test_Thread::Test_Thread(QWidget *parent)
        : QMainWindow(parent)
    {
        ui.setupUi(this);
        widget = new QWidget;
        layout = new QVBoxLayout;
        textBrowser = new QTextBrowser;

        layout->addWidget(textBrowser);
        widget->setLayout(layout);
        setCentralWidget(widget);//在主窗口上显示

        //把对象移动到新线程  
        obj1->moveToThread(t2);
        t2->start();
        connect(t2, SIGNAL(started()), obj1, SLOT(MyThread()));
        connect(obj1, SIGNAL(sendStr(QString)), textBrowser, SLOT(setText(QString)));
    }

    Test_Thread::~Test_Thread()
    {
        delete layout;
        delete textBrowser;
        delete widget;
        delete t2;
        delete obj1;

    }

  1. //mythread.h
    #ifndef MYOBJECT_H
    #define MYOBJECT_H

    #include<QtCore/QObject>

    class MyObject :public QObject
    {
        Q_OBJECT
    public:
        MyObject();
        ~MyObject();
        bool thread_run = true;

    public slots:
        void MyThread();
    private:
        signals:
        void sendStr(QString);
    };

    #endif // MYOBJECT_H

  1. //mythread.cpp
    #include "mythread.h"
    #include<QtCore/QThread>  
    #include<QtCore/QDebug>  

    MyObject::MyObject()
    {

    }

    MyObject::~MyObject()
    {

    }

    void MyObject::MyThread()
    {
        while (thread_run)
        {
            QString str = "内存还在泄漏吗?\r\n";
            //_sleep(100);
            emit sendStr(str);

        }
    }



angelus 2018-01-02 09:32
没看出来那里有内存泄漏!
一个while循环一直在线程里边跑,线程一直都没结束掉,那里来的内存泄漏!


勤为径也 2018-01-02 10:21
angelus:没看出来那里有内存泄漏!
一个while循环一直在线程里边跑,线程一直都没结束掉,那里来的内存泄漏!
(2018-01-02 09:32)

就是。不知道啥原因。

我下载了另一个贴子(

QT多线程示例+一种通用高并发数据处理最简单思路 http://www.qtcn.org/bbs/read-htm-tid-58314.html)中的类似代码,也同样出现内存泄漏问题。

不知道是不是Qt的bug。

请高手指点!!!


小韩老师 2018-01-02 10:33
sendStr(QString);信号也是个函数定义,你需要定义这个形参,不然怎么将实参传输给槽函数

angelus 2018-01-03 16:17
勤为径也:就是。不知道啥原因。
我下载了另一个贴子(
....... (2018-01-02 10:21) 

你是怎么知道的内存出现泄漏的?

勤为径也 2018-01-03 16:36
angelus:你是怎么知道的内存出现泄漏的? (2018-01-03 16:17) 

任务管理器中,内存在不断增加啊。

zhanglyl 2018-01-04 15:25
把QString str移出死循环,立竿见影!

勤为径也 2018-01-04 16:00
zhanglyl:把QString str移出死循环,立竿见影! (2018-01-04 15:25) 

老师,不行啊!

内存还是不断增加啊。

angelus 2018-01-04 16:14
这个问题测试过了,其实并不是内存泄漏,而是使用问题

首先你在线程中发送的 emit 信号是一个异步信号, 异步信号在qt 中都是当作 事件处理的,统一加入到事件队列中
qt的事件队列没有加入防错设置,是一个无限增加的队列,因为是异步,所以当入队事件远远大于出队事件时候,就会把队列塞爆炸,
如果你的机器内存可以非常大,那么程序就会过很久才会因为内存溢出崩溃,不然程序很快就会挂掉.

这个时候有两种方法处理, 原理都是给队列时间去释放内存.

1: 不要用while循环这种没有时间差的处理循环,改用定时器,一定时间去发送信号.
2: 在while循环中,发送信号后,休眠线程,根据你机器的处理能力去决定休眠的时间长短,msleep,usleep,sleep


如果你的信号是一个同步信号,那么就不需要关心上边的,因为执行完信号,就会直接调用槽,然后释放.
永远不会有内存溢出问题!







zhanglyl 2018-01-05 10:23
非要我贴源码
void MyObject::MyThread()
{
  QString str;

  while (thread_run) {
    str = "内存还在泄漏吗?\r\n";
    QThread::msleep(5);

    emit sendStr(str);
  }
}

内容来自[短消息]

angelus 2018-01-05 10:32
zhanglyl:非要我贴源码
void MyObject::MyThread()
{
  QString str;
....... (2018-01-05 10:23) 

你可以试试把 线程休眠去掉!

judesmorning 2018-01-12 13:27
你先找找资料看看正确的线程方式是怎么做的吧
Qt做线程有两种
1、MyObject::QThread
重写run函数,在run里while(1)
2、MyObject::QObject
定义槽函数,槽函数里不要有while(1),槽函数只做一次事情

adc的121 2019-09-29 14:03
楼主解决这个多线程内存泄漏的问题了吗?我遇到了和你一样的问题

yuxiaoqoo 2020-11-23 10:53
QTextBrowser  内存泄漏,设置QTextBrowser 最大行数就好了


查看完整版本: [-- 线程内使用emit(),内存泄漏十分严重,哪里出了问题?有源代码 --] [-- top --]



Powered by phpwind v8.7 Code ©2003-2011 phpwind
Gzip disabled