#c #qt #memory-leaks
Вопрос:
У меня есть два окна, одно с настройками и не запускается при запуске, а другое, которое обновляет информацию каждую минуту. Но в течение некоторого времени я обнаружил, что использование памяти в диспетчере задач медленно увеличивается.
Я устанавливаю Deleaker для отслеживания утечки памяти, но она отображается только в библиотеках QT (QT6Guid.dll и т.д.).
Фрагмент кода обновленного окна, который отображается при запуске:
TaskTrackerScreen::TaskTrackerScreen(Controller *controller, QWidget *parent) :
Screen(controller, parent),
ui(new Ui::TaskTrackerScreen),
m_controller(controller) {
ui->setupUi(this);
m_size = QSize(1200, 900);
m_titleBarHeight = 30;
m_exitButtonWidth = 55;
m_iconExitScale = 0.34f;
m_controller->getTasks();
this->drawTitleBar(this, "SG Task Tracker");
this->drawContent();
m_controller->startActivityScan();
}
TaskTrackerScreen::~TaskTrackerScreen() {
m_controller->stopActivityScan();
delete ui;
delete m_tasksWidgetsContainer;
delete m_playIcon;
delete m_pauseIcon;
delete m_taskListWidget;
delete m_activeTaskWidget;
}
void TaskTrackerScreen::drawContent() {
m_content = Screen::drawContent(this);
m_playIcon = m_pixmapFactory->createElement(":/Icons/play.png", QSize(40, 40));
m_pauseIcon = m_pixmapFactory->createElement(":/Icons/pause.png", QSize(40, 40));
m_activeTaskWidget = m_widgetFactory->createElement(m_content);
m_widgetFactory->applyStyle(m_activeTaskWidget,
QRect(20, 0, 1160, 100),
"border-bottom-left-radius:15px;border-bottom-right-radius:15px;border:2px solid rgb(75,75,75);border-top:0px solid transparent;");
m_activeTaskWidget->setLayout(drawActiveTaskWidget());
m_taskListWidget = m_widgetFactory->createElement();
m_tasksWidgetsContainer = new QVBoxLayout;
m_tasksWidgetsContainer->setContentsMargins(0, 0, 0, 0);
m_tasksWidgetsContainer->setSpacing(5);
drawTasksList();
m_taskListWidget->setLayout(m_tasksWidgetsContainer);
auto scrollArea = m_scrollAreaFactory->createElement(m_content);
m_scrollAreaFactory->applyStyle(scrollArea, QRect(10, 120, 1190, 750));
scrollArea->setWidget(m_taskListWidget);
}
QHBoxLayout* TaskTrackerScreen::drawActiveTaskWidget() {
auto activeTask = m_controller->activeTask();
m_font->setPixelSize(19);
auto layout = new QHBoxLayout();
layout->setContentsMargins(10, 11, 10, 11);
layout->setSpacing(0);
auto indexPushButton = m_pushButtonFactory->createElement();
m_pushButtonFactory->applyStyle(indexPushButton,
QSize(80, 78),
(activeTask != Q_NULLPTR ? activeTask->idReadable() : ""),
m_font,
Q_NULLPTR,
"QPushButton{border:2px solid rgb(75,75,75);}QPushButton:hover{border:2px solid rgb(75,75,75);background-color:rgb(30,30,30);}");
layout->addWidget(indexPushButton, Qt::AlignLeft);
if (m_controller->activeTask() != Q_NULLPTR) {
indexPushButton->setCursor(Qt::PointingHandCursor);
}
connect(indexPushButton, SIGNAL(clicked()), this, SLOT(openIssueLink()));
auto summaryLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(summaryLabel,
m_font,
(activeTask != Q_NULLPTR ? activeTask->summary() : ""),
"margin:0px;padding-bottom:2px;border:2px solid rgb(75,75,75);border-radius:0px;border-bottom:0px solid transparent;");
summaryLabel->setAlignment(Qt::AlignLeft);
summaryLabel->setFixedSize(505, 31);
m_font->setPixelSize(12);
auto descriptionLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(descriptionLabel,
m_font,
(activeTask != Q_NULLPTR ? activeTask->description() : ""),
"margin:0px;padding:8px;border:2px solid rgb(75,75,75);border-top:0px solid transparent;");
descriptionLabel->setWordWrap(true);
descriptionLabel->setAlignment(Qt::AlignLeft);
descriptionLabel->setFixedSize(505, 46);
auto infoLayout = new QVBoxLayout;
infoLayout->setContentsMargins(0, 0, 0, 0);
infoLayout->setSpacing(0);
infoLayout->addWidget(summaryLabel, Qt::AlignLeft);
infoLayout->addWidget(descriptionLabel, Qt::AlignLeft);
layout->addLayout(infoLayout, Qt::AlignLeft);
m_font->setPixelSize(19);
auto priorityLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(priorityLabel,
m_font,
(activeTask != Q_NULLPTR ? activeTask->priority() : ""),
(QString) "margin:0px;border:2px solid rgb(75,75,75);border-radius:0px;");
priorityLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
priorityLabel->setFixedSize(200, 38);
auto stateLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(stateLabel,
m_font,
(activeTask != Q_NULLPTR ? activeTask->state() : ""),
"margin:0px;border:2px solid rgb(75,75,75);border-bottom-right-radius:0px;");
stateLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
stateLabel->setFixedSize(200, 38);
auto detailsLayout = new QVBoxLayout;
detailsLayout->setContentsMargins(0, 0, 0, 0);
detailsLayout->setSpacing(0);
detailsLayout->addWidget(priorityLabel, Qt::AlignLeft);
detailsLayout->addWidget(stateLabel, Qt::AlignLeft);
layout->addLayout(detailsLayout, Qt::AlignLeft);
auto dueDateLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(dueDateLabel,
m_font,
(activeTask != Q_NULLPTR ? "Срок: " QLocale{QLocale::Russian}.toString(activeTask->dueDate(), "dd-MM-yyyy") : "Срок: "),
(QString) "margin:0px;border:2px solid rgb(75,75,75);border-radius:0px;");
dueDateLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
dueDateLabel->setFixedSize(280, 38);
auto spentTimeLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(spentTimeLabel,
m_font,
(activeTask != Q_NULLPTR ? "Затраченно: " activeTask->spentTime().toString() : "Затраченно: "),
"margin:0px;border:2px solid rgb(75,75,75);border-bottom-left-radius:0px;");
spentTimeLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
spentTimeLabel->setFixedSize(280, 38);
auto timeLayout = new QVBoxLayout;
timeLayout->setContentsMargins(0, 0, 0, 0);
timeLayout->setSpacing(0);
timeLayout->addWidget(dueDateLabel, Qt::AlignLeft);
timeLayout->addWidget(spentTimeLabel, Qt::AlignLeft);
layout->addLayout(timeLayout, Qt::AlignLeft);
auto playPauseButton = m_pushButtonFactory->createElement();
if (activeTask != Q_NULLPTR amp;amp; m_controller->isRunning()) {
m_pushButtonFactory->applyStyle(playPauseButton,
QSize(70, 78),
Q_NULLPTR,
Q_NULLPTR,
m_pauseIcon,
"QPushButton{border:2px solid rgb(75,75,75);}QPushButton:hover{border:2px solid rgb(75,75,75);}");
} else {
m_pushButtonFactory->applyStyle(playPauseButton,
QSize(70, 78),
Q_NULLPTR,
Q_NULLPTR,
m_playIcon,
"QPushButton{border:2px solid rgb(75,75,75);}QPushButton:hover{border:2px solid rgb(75,75,75);}");
}
playPauseButton->setIconSize(QSize(40, 40));
if (activeTask == Q_NULLPTR) {
playPauseButton->setEnabled(false);
}
layout->addWidget(playPauseButton, Qt::AlignRight);
connect(playPauseButton, amp;QPushButton::released, m_controller,
[=]() {
auto activeTask = m_controller->activeTask();
if (activeTask != Q_NULLPTR amp;amp; m_controller->isRunning()) {
m_controller->stopTimeTrack();
m_pushButtonFactory->applyStyle(playPauseButton,
QSize(70, 78),
Q_NULLPTR,
Q_NULLPTR,
m_playIcon,
"QPushButton{border:2px solid rgb(75,75,75);}QPushButton:hover{border:2px solid rgb(75,75,75);}");
m_pushButtonFactory->applyStyle((QPushButton*) activeTask
->widgetSlot()
->layout()
->itemAt(4)
->widget(),
QSize(70, 78),
Q_NULLPTR,
Q_NULLPTR,
m_playIcon,
"QPushButton{border:2px solid rgb(75,75,75);}QPushButton:hover{border:2px solid rgb(75,75,75);}");
} else {
m_controller->startTimeTrack(activeTask);
m_pushButtonFactory->applyStyle(playPauseButton,
QSize(70, 78),
Q_NULLPTR,
Q_NULLPTR,
m_pauseIcon,
"QPushButton{border:2px solid rgb(75,75,75);}QPushButton:hover{border:2px solid rgb(75,75,75);}");
if (activeTask != Q_NULLPTR) {
m_pushButtonFactory->applyStyle((QPushButton*) activeTask
->widgetSlot()
->layout()
->itemAt(4)
->widget(),
QSize(70, 78),
Q_NULLPTR,
Q_NULLPTR,
m_pauseIcon,
"QPushButton{border:2px solid rgb(75,75,75);}QPushButton:hover{border:2px solid rgb(75,75,75);}");
}
}
});
return layout;
}
void TaskTrackerScreen::openIssueLink() {
auto activeTask = m_controller->activeTask();
if (activeTask != Q_NULLPTR) {
QDesktopServices::openUrl(QUrl(ConfigManager::config.baseUrl "/issue/" activeTask->idReadable() "/", QUrl::TolerantMode));
}
}
void TaskTrackerScreen::drawTasksList() {
while (m_tasksWidgetsContainer->itemAt(0) != Q_NULLPTR) {
auto taskWidget = m_tasksWidgetsContainer->itemAt(0)->widget();
m_tasksWidgetsContainer->removeWidget(taskWidget);
delete taskWidget;
}
auto tasks = m_controller->tasks();
m_widgetFactory->applyStyle(m_taskListWidget, QRect(0, 0, 1180, tasks.size() * 85));
auto index = 0;
for (auto task : tasks) {
m_tasksWidgetsContainer->addWidget(drawTaskWidget(task, index, 80));
index ;
}
}
QWidget* TaskTrackerScreen::drawTaskWidget(Task *task, int id, int height) {
m_font->setPixelSize(19);
auto widget = m_widgetFactory->createElement();
m_widgetFactory->applyStyle(widget,
QRect(0, 0, 1175, height),
"border:2px solid rgb(75,75,75);");
auto layout = new QHBoxLayout(widget);
layout->setContentsMargins(2, 2, 2, 2);
layout->setSpacing(0);
auto indexLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(indexLabel,
m_font,
QString::number(id 1),
"margin:0px;border-right:2px solid rgb(75,75,75);");
layout->addWidget(indexLabel, Qt::AlignLeft);
indexLabel->setFixedWidth(80);
auto summaryLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(summaryLabel,
m_font,
task->summary(),
"margin:0px;margin-left:-2px;");
summaryLabel->setAlignment(Qt::AlignLeft);
summaryLabel->setFixedSize(545, qRound((height - 4) * 0.4));
m_font->setPixelSize(12);
auto descriptionLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(descriptionLabel,
m_font,
task->description(),
"margin:0px;margin-top:-5px;");
descriptionLabel->setWordWrap(true);
descriptionLabel->setAlignment(Qt::AlignLeft);
descriptionLabel->setFixedSize(545, qRound((height - 4) * 0.6));
auto infoLayout = new QVBoxLayout;
infoLayout->setContentsMargins(0, 0, 0, 0);
infoLayout->setSpacing(0);
infoLayout->addWidget(summaryLabel, Qt::AlignLeft);
infoLayout->addWidget(descriptionLabel, Qt::AlignLeft);
layout->addLayout(infoLayout, Qt::AlignLeft);
m_font->setPixelSize(19);
auto priorityLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(priorityLabel,
m_font,
task->priority(),
(QString) "margin:0px;border:2px solid rgb(75,75,75);border-top:0px solid transparent;"
(QString) (task->priority() == SGTT::Priority_Ru[4] ? "color:rgb(255,179,25);" : ""));
priorityLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
priorityLabel->setFixedSize(200, qRound((height - 4) * 0.5));
auto stateLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(stateLabel,
m_font,
task->state(),
"margin:0px;border:2px solid rgb(75,75,75);border-bottom:0px solid transparent;");
stateLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
stateLabel->setFixedSize(200, qRound((height - 4) * 0.5));
auto detailsLayout = new QVBoxLayout;
detailsLayout->setContentsMargins(0, 0, 0, 0);
detailsLayout->setSpacing(0);
detailsLayout->addWidget(priorityLabel, Qt::AlignLeft);
detailsLayout->addWidget(stateLabel, Qt::AlignLeft);
layout->addLayout(detailsLayout, Qt::AlignLeft);
auto dueDateLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(dueDateLabel,
m_font,
"Срок: " QLocale{QLocale::Russian}.toString(task->dueDate(), "dd-MM-yyyy"),
(QString) "margin:0px;border:2px solid rgb(75,75,75);border-top:0px solid transparent;"
(QString) (QDate::currentDate() >= task->dueDate() ? "color:rgb(255,179,25);" : ""));
dueDateLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
dueDateLabel->setFixedSize(280, qRound((height - 4) * 0.5));
auto spentTimeLabel = m_labelFactory->createElement();
m_labelFactory->applyStyle(spentTimeLabel,
m_font,
"Затраченно: " task->spentTime().toString(),
"margin:0px;border:2px solid rgb(75,75,75);border-bottom:0px solid transparent;");
spentTimeLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
spentTimeLabel->setFixedSize(280, qRound((height - 4) * 0.5));
auto timeLayout = new QVBoxLayout;
timeLayout->setContentsMargins(0, 0, 0, 0);
timeLayout->setSpacing(0);
timeLayout->addWidget(dueDateLabel, Qt::AlignLeft);
timeLayout->addWidget(spentTimeLabel, Qt::AlignLeft);
layout->addLayout(timeLayout, Qt::AlignLeft);
auto playPauseButton = m_pushButtonFactory->createElement();
auto activeTask = m_controller->activeTask();
if (activeTask != Q_NULLPTR amp;amp; m_controller->isRunning() amp;amp; activeTask->idReadable() == task->idReadable()) {
m_pushButtonFactory->applyStyle(playPauseButton,
QSize(70, (height - 4)),
Q_NULLPTR,
Q_NULLPTR,
m_pauseIcon);
} else {
m_pushButtonFactory->applyStyle(playPauseButton,
QSize(70, (height - 4)),
Q_NULLPTR,
Q_NULLPTR,
m_playIcon);
}
playPauseButton->setIconSize(QSize(40, 40));
layout->addWidget(playPauseButton, Qt::AlignRight);
task->setWidgetSlot(widget);
connect(playPauseButton, amp;QPushButton::released, m_controller,
[=]() {
auto activeTask = m_controller->activeTask();
if (activeTask != Q_NULLPTR amp;amp; m_controller->isRunning() amp;amp; activeTask->idReadable() == task->idReadable()) {
m_controller->stopTimeTrack();
m_pushButtonFactory->applyStyle(playPauseButton,
QSize(70, 76),
Q_NULLPTR,
Q_NULLPTR,
m_playIcon);
} else {
if (activeTask != Q_NULLPTR amp;amp; m_controller->isRunning()) {
m_pushButtonFactory->applyStyle((QPushButton*) activeTask
->widgetSlot()
->layout()
->itemAt(4)
->widget(),
QSize(70, 76),
Q_NULLPTR,
Q_NULLPTR,
m_playIcon);
}
m_controller->startTimeTrack(task);
m_pushButtonFactory->applyStyle(playPauseButton,
QSize(70, 76),
Q_NULLPTR,
Q_NULLPTR,
m_pauseIcon);
}
redrawActiveWidgetLayout();
});
return widget;
}
void TaskTrackerScreen::redrawActiveWidgetLayout() {
delete m_activeTaskWidget->layout();
m_activeTaskWidget->setLayout(drawActiveTaskWidget());
}
void TaskTrackerScreen::redrawSpentTimeWidgets() {
auto activeTask = m_controller->activeTask();
auto widget = activeTask->widgetSlot();
auto spentTimeLabel = (QLabel*) widget
->layout()
->itemAt(3)
->layout()
->itemAt(1)
->widget();
spentTimeLabel->setText("Затраченно: " activeTask->spentTime().toString());
spentTimeLabel = (QLabel*) m_activeTaskWidget
->layout()
->itemAt(3)
->layout()
->itemAt(1)
->widget();
spentTimeLabel->setText("Затраченно: " activeTask->spentTime().toString());
}
Заводы по производству элементов:
QPixmap *QPixmapFactory::createElement(QWidget *parent) {
parent = Q_NULLPTR;
return new QPixmap;
}
QPixmap *QPixmapFactory::createElement(QString fileName, QSize size) {
auto newElement = new QPixmap(fileName);
auto element = newElement->scaled(size, Qt::KeepAspectRatio);
delete newElement;
return new QPixmap(element);
}
QPixmap* QPixmapFactory::changeColor(QPixmap *element, QColor maskColor, QColor objectColor) {
auto newElement = new QPixmap(element->size());
newElement->fill(objectColor);
newElement->setMask(element->createMaskFromColor(maskColor));
delete element;
return newElement;
}
QPixmap* QPixmapFactory::changeScale(QPixmap *element, float scale) {
auto newElement = element->scaled(element->size() * scale, Qt::KeepAspectRatio);
delete element;
return new QPixmap(newElement);
}
inline QWidget* createElement(QWidget *parent = Q_NULLPTR) override { return new QWidget(parent); }
void QWidgetFactory::applyStyle(QWidget *element, QRect geometry, QString additionalStyleSheet) {
auto styleSheet = (QString) "background-color:rgb(25,25,25);";
element->setMinimumSize(geometry.width(), geometry.height());
element->setMaximumSize(geometry.width(), geometry.height());
element->setGeometry(geometry);
if (additionalStyleSheet != Q_NULLPTR) {
styleSheet.append(additionalStyleSheet);
}
element->setStyleSheet(styleSheet);
}
inline QScrollArea* createElement(QWidget *parent = Q_NULLPTR) override { return new QScrollArea(parent); }
void QScrollAreaFactory::applyStyle(QScrollArea *element, QRect geometry, QString additionalStyleSheet) {
auto styleSheet = (QString) "QScrollBar:vertical {"
" border: 1px solid rgb(25,25,25);"
" background:rgb(25,25,25);"
" width:10px; "
" margin: 0px 0px 0px 0px;"
"}"
"QScrollBar::handle:vertical {"
" background: rgb(25,25,25);"
" min-height: 0px;"
"}"
"QScrollBar::add-line:vertical {"
" background: rgb(25,25,25);"
" height: 0px;"
" subcontrol-position: bottom;"
" subcontrol-origin: margin;"
"}"
"QScrollBar::sub-line:vertical {"
" background: rgb(25,25,25);"
" height: 0 px;"
" subcontrol-position: top;"
" subcontrol-origin: margin;"
"}";
element->setGeometry(geometry);
if (additionalStyleSheet != Q_NULLPTR) {
styleSheet.append(additionalStyleSheet);
}
element->verticalScrollBar()->setStyleSheet(styleSheet);
element->horizontalScrollBar()->setStyleSheet("width: 0px;");
element->setStyleSheet("border:0px solid transparent;");
}
inline QPushButton* createElement(QWidget *parent = Q_NULLPTR) override { return new QPushButton(parent); }
void QPushButtonFactory::applyStyle(QPushButton *element,
QSize size,
QString text,
QFont *font,
QPixmap *icon,
QString additionalStyleSheet) {
auto styleSheet = (QString) "QPushButton{border:1px solid rgb(75,75,75);background-color:rgb(30,30,30);color:rgb(240,240,240);}QPushButton:hover{background-color:rgb(60,60,60);color:rgb(240,240,240);}";
if (text != Q_NULLPTR) {
element->setText(text);
}
if (font != Q_NULLPTR) {
font->setPointSize(16);
element->setFont(*font);
}
if (icon != Q_NULLPTR) {
element->setIcon(*icon);
}
if (additionalStyleSheet != Q_NULLPTR) {
styleSheet.append(additionalStyleSheet);
}
element->setStyleSheet(styleSheet);
if (size.height() != 0) {
element->setFixedSize(size);
}
}
inline QLabel* createElement(QWidget *parent = Q_NULLPTR) override { return new QLabel(parent); }
void QLabelFactory::applyStyle(QLabel *element, QFont *font, QString text, QString additionalStyleSheet) {
auto styleSheet = (QString) "padding:5px;margin:5px;color:rgb(240,240,240);border:0px solid white;";
element->setText(text);
element->setFont(*font);
if (additionalStyleSheet != Q_NULLPTR) {
styleSheet.append(additionalStyleSheet);
}
element->setStyleSheet(styleSheet);
element->setAlignment(Qt::AlignCenter);
}
А вот xml-файл результатов удаления: https://dropmefiles.com/OoyMb]
Я не понимаю, почему stacktrace показывает проблему с QLineEdit, если в виджете нет этого элемента…
Комментарии:
1. Вы пробовали сделать два снимка, а затем понять разницу? Это должно помочь пересмотреть только «совокупные» ассигнования? Есть ли шансы поделиться файлом моментального снимка (*.dsnapshot)?
2. @ArtemRazin вот два реальных снимка dropmefiles.com/irJMy Извините за поздний ответ