问题描述
我们正面临与内存使用量增加相关的问题 QObject::connect 在我们的应用程序中调用。这导致应用程序崩溃 连续执行 16~17 小时后。在这里,我们试图了解 由于 QObject::connect 调用而导致内存使用量增加的原因,如果有 是处理相同问题的任何特定方式。 为了模拟相同,我创建了一个示例应用程序,它执行以下操作(请参阅 应用屏幕截图以便更好地理解):
-
按下“开始”按钮后,应用程序将开始创建 以 50 毫秒的间隔在一个单独的类中对象指针 线。类的每个对象指针都会创建一个缓冲区 内部 1000 字节。并且新的指针将被存储在一个列表中 (它是对象创建线程的成员变量)。在每个 新对象的创建同样会被通知到 MainWindow( ui 线程),带有创建的对象指针。
-
在对象创建线程的通知下,MainWindow 可以 根据“使用连接”复选框执行以下 2 个操作 状态:
一个。将局部成员变量初始化为新对象 创建。
湾断开/连接到 new 的 destroy() 信号 对象创建到插槽,如果“使用连接”复选框被选中。
观察:
- 我们运行了 5 分钟的示例应用程序并收集了结果 “带连接”和“不带连接”方法调用。 为这两种情况收集了 5 个样本。
- “无连接”调用的内存使用量约为 8.5 Mb (收集的所有 5 个样本几乎不变)
- “With connect call”的内存使用量约为 9.7 Mb (收集的所有 5 个样本几乎不变)
- 以上结果表明,当连接调用发生时,内存使用量为 增加。这就是在实际项目中观察到的情况。
我们正在尝试了解额外内存使用的原因,以防万一 “使用连接”调用并需要相同的解决方案/建议。
请让我们知道您对此的意见。
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
mainwindow.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 (将#修改为@)