• 6248阅读
  • 13回复

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

上一主题 下一主题
离线勤为径也
 

只看楼主 倒序阅读 楼主  发表于: 2018-01-01
一个十分简单的QT程序,线程启动后内存泄漏十分严重。
QT新手请高手指点。谢谢!!
  1. //main.cpp
  2. #include "test_thread.h"
  3. #include <QtWidgets/QApplication>
  4. int main(int argc, char *argv[])
  5. {
  6.     QApplication a(argc, argv);
  7.     Test_Thread w;
  8.     w.show();
  9.     return a.exec();
  10. }

  1. //test_thread.h
  2. #ifndef TEST_THREAD_H
  3. #define TEST_THREAD_H
  4. #include <QtWidgets/QMainWindow>
  5. #include "ui_test_thread.h"
  6. #include <QtWidgets/QTextBrowser>
  7. #include <QtWidgets/QWidget>
  8. #include <QtWidgets/QLayout>
  9. #include<QtCore/QThread>  
  10. #include "mythread.h"
  11. class Test_Thread : public QMainWindow
  12. {
  13.     Q_OBJECT
  14. public:
  15.     Test_Thread(QWidget *parent = 0);
  16.     ~Test_Thread();
  17.     Ui::Test_ThreadClass ui;
  18.     QWidget *widget;
  19.     QVBoxLayout *layout;
  20.     QTextBrowser *textBrowser;
  21. private:
  22.     void creat_Label();
  23.     QThread * t2 = new QThread();
  24.     MyObject * obj1 = new MyObject();
  25. };
  26. #endif // TEST_THREAD_H

  1. //test_thread.cpp
  2. #include "test_thread.h"
  3. #include <QtCore/QDebug>
  4. Test_Thread::Test_Thread(QWidget *parent)
  5.     : QMainWindow(parent)
  6. {
  7.     ui.setupUi(this);
  8.     widget = new QWidget;
  9.     layout = new QVBoxLayout;
  10.     textBrowser = new QTextBrowser;
  11.     layout->addWidget(textBrowser);
  12.     widget->setLayout(layout);
  13.     setCentralWidget(widget);//在主窗口上显示
  14.     //把对象移动到新线程  
  15.     obj1->moveToThread(t2);
  16.     t2->start();
  17.     connect(t2, SIGNAL(started()), obj1, SLOT(MyThread()));
  18.     connect(obj1, SIGNAL(sendStr(QString)), textBrowser, SLOT(setText(QString)));
  19. }
  20. Test_Thread::~Test_Thread()
  21. {
  22.     delete layout;
  23.     delete textBrowser;
  24.     delete widget;
  25.     delete t2;
  26.     delete obj1;
  27. }

  1. //mythread.h
  2. #ifndef MYOBJECT_H
  3. #define MYOBJECT_H
  4. #include<QtCore/QObject>
  5. class MyObject :public QObject
  6. {
  7.     Q_OBJECT
  8. public:
  9.     MyObject();
  10.     ~MyObject();
  11.     bool thread_run = true;
  12. public slots:
  13.     void MyThread();
  14. private:
  15.     signals:
  16.     void sendStr(QString);
  17. };
  18. #endif // MYOBJECT_H

  1. //mythread.cpp
  2. #include "mythread.h"
  3. #include<QtCore/QThread>  
  4. #include<QtCore/QDebug>  
  5. MyObject::MyObject()
  6. {
  7. }
  8. MyObject::~MyObject()
  9. {
  10. }
  11. void MyObject::MyThread()
  12. {
  13.     while (thread_run)
  14.     {
  15.         QString str = "内存还在泄漏吗?\r\n";
  16.         //_sleep(100);
  17.         emit sendStr(str);
  18.     }
  19. }


离线angelus

只看该作者 1楼 发表于: 2018-01-02
没看出来那里有内存泄漏!
一个while循环一直在线程里边跑,线程一直都没结束掉,那里来的内存泄漏!

离线勤为径也

只看该作者 2楼 发表于: 2018-01-02
回 angelus 的帖子
angelus:没看出来那里有内存泄漏!
一个while循环一直在线程里边跑,线程一直都没结束掉,那里来的内存泄漏!
(2018-01-02 09:32)

就是。不知道啥原因。

我下载了另一个贴子(

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

不知道是不是Qt的bug。

请高手指点!!!

离线小韩老师

只看该作者 3楼 发表于: 2018-01-02
sendStr(QString);信号也是个函数定义,你需要定义这个形参,不然怎么将实参传输给槽函数
离线angelus

只看该作者 4楼 发表于: 2018-01-03
回 勤为径也 的帖子
勤为径也:就是。不知道啥原因。
我下载了另一个贴子(
....... (2018-01-02 10:21) 

你是怎么知道的内存出现泄漏的?
离线勤为径也

只看该作者 5楼 发表于: 2018-01-03
回 angelus 的帖子
angelus:你是怎么知道的内存出现泄漏的? (2018-01-03 16:17) 

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

只看该作者 6楼 发表于: 2018-01-04
把QString str移出死循环,立竿见影!
离线勤为径也

只看该作者 7楼 发表于: 2018-01-04
回 zhanglyl 的帖子
zhanglyl:把QString str移出死循环,立竿见影! (2018-01-04 15:25) 

老师,不行啊!

内存还是不断增加啊。
离线angelus

只看该作者 8楼 发表于: 2018-01-04
回 勤为径也 的帖子
这个问题测试过了,其实并不是内存泄漏,而是使用问题

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

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

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


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






离线zhanglyl

只看该作者 9楼 发表于: 2018-01-05
非要我贴源码
void MyObject::MyThread()
{
  QString str;

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

    emit sendStr(str);
  }
}

内容来自[短消息]
离线angelus

只看该作者 10楼 发表于: 2018-01-05
回 zhanglyl 的帖子
zhanglyl:非要我贴源码
void MyObject::MyThread()
{
  QString str;
....... (2018-01-05 10:23) 

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

只看该作者 11楼 发表于: 2018-01-12
你先找找资料看看正确的线程方式是怎么做的吧
Qt做线程有两种
1、MyObject::QThread
重写run函数,在run里while(1)
2、MyObject::QObject
定义槽函数,槽函数里不要有while(1),槽函数只做一次事情
离线adc的121

只看该作者 12楼 发表于: 2019-09-29
楼主解决这个多线程内存泄漏的问题了吗?我遇到了和你一样的问题
离线yuxiaoqoo

只看该作者 13楼 发表于: 2020-11-23
QTextBrowser  内存泄漏,设置QTextBrowser 最大行数就好了
快速回复
限100 字节
 
上一个 下一个