微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

增加 QObject::connect call

如何解决增加 QObject::connect call

我们正面临与内存使用量增加相关的问题 QObject::connect 在我们的应用程序中调用。这导致应用程序崩溃 连续执行 16~17 小时后。在这里,我们试图了解 由于 QObject::connect 调用而导致内存使用量增加的原因,如果有 是处理相同问题的任何特定方式。 为了模拟相同,我创建了一个示例应用程序,它执行以下操作(请参阅 应用屏幕截图以便更好地理解):

  1. 按下“开始”按钮后,应用程序将开始创建 以 50 毫秒的间隔在一个单独的类中对象指针 线。类的每个对象指针都会创建一个缓冲区 内部 1000 字节。并且新的指针将被存储在一个列表中 (它是对象创建线程的成员变量)。在每个 新对象的创建同样会被通知到 MainWindow( ui 线程),带有创建的对象指针。

  2. 对象创建线程的通知下,MainWindow 可以 根据“使用连接”复选框执行以下 2 个操作 状态:

    一个。将局部成员变量初始化为新对象 创建。
    湾断开/连接到 new 的 destroy() 信号 对象创建到插槽,如果“使用连接”复选框被选中。

enter image description here

观察:

  1. 我们运行了 5 分钟的示例应用程序并收集了结果 “带连接”和“不带连接”方法调用。 为这两种情况收集了 5 个样本。
  2. “无连接”调用的内存使用量约为 8.5 Mb (收集的所有 5 个样本几乎不变)
  3. “With connect call”的内存使用量约为 9.7 Mb (收集的所有 5 个样本几乎不变)
  4. 以上结果表明,当连接调用发生时,内存使用量为 增加。这就是在实际项目中观察到的情况。

我们正在尝试了解额外内存使用的原因,以防万一 “使用连接”调用并需要相同的解决方案/建议。

请让我们知道您对此的意见。
Main.cpp

#include <QApplication>

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

HeavyClass.cpp

#include "HeavyClass.h"
#include <QDateTime>

const unsigned int CHeaveyClass::kArraySize = 1000;

CHeaveyClass::CHeaveyClass(QObject *parent)
    : QObject(parent),m_pForMemAllocaion(nullptr)
{
    m_pForMemAllocaion = new char[kArraySize];
    if (m_pForMemAllocaion)
    {
        memset(m_pForMemAllocaion,kArraySize);
        sprintf_s(m_pForMemAllocaion,kArraySize,"I am created at Bikash %s",QDateTime::currentDateTime().toString().toStdString().c_str());
    }
}

CHeaveyClass::~CHeaveyClass()
{
    if (m_pForMemAllocaion)
    {
        delete m_pForMemAllocaion;
        m_pForMemAllocaion = nullptr;
    }
}

HeaveyClass.h

#ifndef CHEAVYCLASS_H
#define CHEAVYCLASS_H

#include <QObject>

class CHeaveyClass : public QObject
{
    Q_OBJECT

public:
    explicit CHeaveyClass(QObject *parent = nullptr);
    ~CHeaveyClass();
signals:

private:
     char* m_pForMemAllocaion;
     const static unsigned int kArraySize;
};

#endif // CHEAVYCLASS_H

MainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "MyThread.h"
#include "HeavyClass.h"
#include <QTimer>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),ui(new Ui::MainWindow),m_pHeaveyClass(nullptr),m_pTimer(nullptr)
{
    ui->setupUi(this);
    ui->clearMemoryButton->setEnabled(false);
    m_pMyThread = new CMyThread(nullptr,this);
    if (m_pMyThread)
    {
        connect(m_pMyThread,SIGNAL(listSizeChanged(unsigned int)),this,SLOT(OnListSizeChanged(unsigned int)));
    }
    m_pTimer = new QTimer();
    if (m_pTimer)
    {
        connect(m_pTimer,SIGNAL(timeout()),SLOT(OnTimerTimeOut()));
    }
}

MainWindow::~MainWindow()
{
    if (m_pMyThread)
    {
        disconnect(m_pMyThread,SLOT(OnListSizeChanged(unsigned int)));
        delete m_pMyThread;
        m_pMyThread = nullptr;
    }
    if (m_pTimer)
    {
        if (m_pTimer->isActive())
        {
            m_pTimer->stop();
        }
        disconnect(m_pTimer,SLOT(OnTimerTimeOut()));
        delete m_pTimer;
        m_pTimer = nullptr;
    }

    delete ui;
}


void MainWindow::on_startButton_clicked()
{
    if (0 == ui->startButton->text().compare("start",Qt::CaseInsensitive))
    {
        ui->startButton->setText("Stop");
        ui->clearMemoryButton->setEnabled(false);
        if (m_pMyThread)
        {
            m_pMyThread->start();
        }
        if (m_pTimer)
        {
            m_tStartTime = QTime::currentTime();
            m_pTimer->start(1000);
        }
    }
    else
    {
        ui->startButton->setText("Start");
        ui->timeLabel->clear();
        ui->ranFor->clear();
        if (m_pMyThread)
        {
            m_pMyThread->StopThread();
        }
        if (m_pTimer)
        {
            m_pTimer->stop();
        }
    }
}

void MainWindow::OnListSizeChanged(unsigned int size)
{
    ui->clearMemoryButton->setEnabled(size > 0 ? true : false);
}

void MainWindow::setPrefferedHeavyObject(CHeaveyClass *ptr)
{
    Q_UNUSED(ptr)
    if (ui->useConnect->checkState() == Qt::Checked)
        disconnect(m_pHeaveyClass,SIGNAL(destroyed(QObject*)));

    m_pHeaveyClass = ptr;

    if (ui->useConnect->checkState() == Qt::Checked)
        connect(m_pHeaveyClass,SIGNAL(destroyed(QObject*)),SLOT(OnPrefferedHeavyObjectDeleted(QObject*)));
}

void MainWindow::on_clearMemoryButton_clicked()
{
    m_pMyThread->ClearMemory();
}

void MainWindow::OnPrefferedHeavyObjectDeleted(QObject *ptr)
{
    Q_UNUSED(ptr)
    m_pHeaveyClass = nullptr;
}

void MainWindow::OnTimerTimeOut()
{
    QTime currentTime = QTime::currentTime();
    ui->timeLabel->setText("Current Time : " + currentTime.toString());
    int timeDiffInSecs = m_tStartTime.secsTo(currentTime);
    ui->ranFor->setText("Ran for : " + QString::number(timeDiffInSecs) + " secs");
    if (timeDiffInSecs == 300)
    {
        on_startButton_clicked();
    }
}

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "IMainWindow.h"
#include <QTime>


class CHeaveyClass;
class CMyThread;
class QTimer;

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow
        : public QMainWindow,public IMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_startButton_clicked();
    void OnListSizeChanged(unsigned int size);
    void on_clearMemoryButton_clicked();
    void OnPrefferedHeavyObjectDeleted(QObject* ptr);
    void OnTimerTimeOut();


    // IMainWindow interface
protected:
    void setPrefferedHeavyObject(CHeaveyClass *ptr);

private:
    Ui::MainWindow *ui;
    CHeaveyClass* m_pHeaveyClass;
    CMyThread* m_pMyThread;
    QTimer* m_pTimer;
    QTime m_tStartTime;
};
#endif // MAINWINDOW_H

MyThread.cpp

#include "MyThread.h"
#include "HeavyClass.h"
#include <QDebug>
#include "IMainWindow.h"
CMyThread::CMyThread(QObject *pParent,IMainWindow* pMainWindowInterface)
    : QThread(pParent),m_pMainWindow(pMainWindowInterface)
{
    m_lstHeavyClass.clear();
}

CMyThread::~CMyThread()
{
    StopThread();
    while (isRunning());
    ClearMemory();
    qDebug() << "Destroying the thread.";
}

void CMyThread::StopThread()
{
    m_bContinueExecution = false;
}

void CMyThread::ClearMemory()
{
    if (false == isRunning())
    {
        while (m_lstHeavyClass.size() != 0)
        {
            CHeaveyClass* p = m_lstHeavyClass.last();
            m_lstHeavyClass.removeLast();
            delete p;
            p = nullptr;
            listSizeChanged(m_lstHeavyClass.size());
        }
        qDebug() << "All created heavy class ptrs are deleted.";
    }
    else
    {
        qDebug() << "Thread is still active. Stop the thread first.";
    }

}

void CMyThread::run()
{
    m_bContinueExecution = true;
    while (m_bContinueExecution)
    {
        CHeaveyClass * pHeavyClass = new CHeaveyClass();
        if (pHeavyClass)
        {
            m_lstHeavyClass.append(pHeavyClass);
            m_pMainWindow->setPrefferedHeavyObject(pHeavyClass);
            listSizeChanged(m_lstHeavyClass.size());
            msleep(50);
        }
    }
    qDebug() << "Stopping thread execution.";
}

MyThread.h

#ifndef CMYTHREAD_H
#define CMYTHREAD_H

#include <QThread>
class IMainWindow;
class CHeaveyClass;
class CMyThread : public QThread
{
    Q_OBJECT
public:
    explicit CMyThread(QObject* pParent = nullptr,IMainWindow* pMainWindowInterface = nullptr);
    ~CMyThread();
    void StopThread();
    void ClearMemory();
    // QThread interface
signals:
    void listSizeChanged(unsigned int size);
protected:
    void run();
private:
    bool    m_bContinueExecution;
    IMainWindow* m_pMainWindow;
    QList<CHeaveyClass*> m_lstHeavyClass;
};

#endif // CMYTHREAD_H

IMainWindow.h

#ifndef IMAINWINDOW_H
#define IMAINWINDOW_H

class CHeaveyClass;

class IMainWindow {
public:
    virtual void setPrefferedHeavyObject(CHeaveyClass* ptr) = 0;
};

#endif // IMAINWINDOW_H

ma​​inwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>400</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout_3">
    <item>
     <layout class="QVBoxLayout" name="verticalLayout_2">
      <item>
       <layout class="QHBoxLayout" name="horizontalLayout">
        <item>
         <widget class="QPushButton" name="startButton">
          <property name="text">
           <string>Start</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="useConnect">
          <property name="text">
           <string>Use Connect</string>
          </property>
         </widget>
        </item>
       </layout>
      </item>
      <item>
       <widget class="QPushButton" name="clearMemoryButton">
        <property name="text">
         <string>Clear Memory</string>
        </property>
       </widget>
      </item>
      <item>
       <layout class="QVBoxLayout" name="verticalLayout">
        <item>
         <spacer name="verticalSpacer">
          <property name="orientation">
           <enum>Qt::Vertical</enum>
          </property>
          <property name="sizeHint" stdset="0">
           <size>
            <width>20</width>
            <height>40</height>
           </size>
          </property>
         </spacer>
        </item>
        <item>
         <widget class="QLabel" name="timeLabel">
          <property name="text">
           <string/>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QLabel" name="ranFor">
          <property name="text">
           <string/>
          </property>
         </widget>
        </item>
       </layout>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>400</width>
     <height>26</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。