From ae26a813b89c4a73148d691659fc379a816054d8 Mon Sep 17 00:00:00 2001 From: cristian64 Date: Sat, 18 May 2024 12:15:09 +0100 Subject: [PATCH 1/2] Avoid memory leak in `MemWatchModel::importRootFromCTFile()`. The existing root node (`m_rootNode`) was not being deleted before being entirely replaced with another pointer. --- Source/GUI/MemWatcher/MemWatchModel.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/GUI/MemWatcher/MemWatchModel.cpp b/Source/GUI/MemWatcher/MemWatchModel.cpp index 535d3f6..fcd54b1 100644 --- a/Source/GUI/MemWatcher/MemWatchModel.cpp +++ b/Source/GUI/MemWatcher/MemWatchModel.cpp @@ -702,7 +702,10 @@ MemWatchModel::CTParsingErrors MemWatchModel::importRootFromCTFile(QFile* const parser.setTableStartAddress(CEStart); MemWatchTreeNode* importedRoot = parser.parseCTFile(CTFile, useDolphinPointer); if (importedRoot != nullptr) + { + delete m_rootNode; m_rootNode = importedRoot; + } CTParsingErrors parsingErrors; parsingErrors.errorStr = parser.getErrorMessages(); From f5359e21778cc3dc2151c52b61dcfec50f1a652a Mon Sep 17 00:00:00 2001 From: cristian64 Date: Fri, 17 May 2024 21:50:56 +0100 Subject: [PATCH 2/2] Replace use of `layoutChanged()` with more specific alternatives. `dataChanged()`, or `beginModelReset()` and `endModelReset()` are now used. Note that, whilst `layoutChanged()` can be used, it is generally used for layout changes, and not specific data changes or full model resets, and it generally needs a matching `layoutAboutToBeChanged()` call in advance. --- Source/GUI/MemWatcher/MemWatchModel.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Source/GUI/MemWatcher/MemWatchModel.cpp b/Source/GUI/MemWatcher/MemWatchModel.cpp index fcd54b1..0ecd917 100644 --- a/Source/GUI/MemWatcher/MemWatchModel.cpp +++ b/Source/GUI/MemWatcher/MemWatchModel.cpp @@ -176,7 +176,7 @@ void MemWatchModel::editEntry(MemWatchEntry* entry, const QModelIndex& index) { MemWatchTreeNode* node = static_cast(index.internalPointer()); node->setEntry(entry); - emit layoutChanged(); + emit dataChanged(index.siblingAtColumn(0), index.siblingAtColumn(columnCount({}) - 1)); } void MemWatchModel::clearRoot() @@ -690,8 +690,9 @@ void MemWatchModel::sortRecursive(int column, Qt::SortOrder order, MemWatchTreeN void MemWatchModel::loadRootFromJsonRecursive(const QJsonObject& json) { + beginResetModel(); m_rootNode->readFromJson(json); - emit layoutChanged(); + endResetModel(); } MemWatchModel::CTParsingErrors MemWatchModel::importRootFromCTFile(QFile* const CTFile, @@ -703,17 +704,13 @@ MemWatchModel::CTParsingErrors MemWatchModel::importRootFromCTFile(QFile* const MemWatchTreeNode* importedRoot = parser.parseCTFile(CTFile, useDolphinPointer); if (importedRoot != nullptr) { + beginResetModel(); delete m_rootNode; m_rootNode = importedRoot; + endResetModel(); } - CTParsingErrors parsingErrors; - parsingErrors.errorStr = parser.getErrorMessages(); - parsingErrors.isCritical = parser.hasACriticalErrorOccured(); - if (!parsingErrors.isCritical) - emit layoutChanged(); - - return parsingErrors; + return {parser.getErrorMessages(), parser.hasACriticalErrorOccured()}; } void MemWatchModel::writeRootToJsonRecursive(QJsonObject& json) const