From b14c76c1c5ca87a633b8d2e3c2fdb29e029e3119 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 27 Apr 2026 21:14:32 +0200 Subject: [PATCH] Qt: fix memory leak in confg_database --- rpcs3/main_application.cpp | 4 +-- rpcs3/rpcs3qt/config_database.cpp | 18 +++++++----- rpcs3/rpcs3qt/config_database.h | 4 +-- rpcs3/rpcs3qt/game_compatibility.cpp | 18 +++++++----- rpcs3/rpcs3qt/game_compatibility.h | 42 +++++++++++++-------------- rpcs3/rpcs3qt/game_list_frame.cpp | 4 +-- rpcs3/rpcs3qt/gui_settings.cpp | 4 +-- rpcs3/rpcs3qt/persistent_settings.cpp | 2 +- rpcs3/rpcs3qt/qt_utils.cpp | 2 +- rpcs3/rpcs3qt/settings.cpp | 10 ++----- rpcs3/rpcs3qt/settings.h | 5 +--- 11 files changed, 51 insertions(+), 62 deletions(-) diff --git a/rpcs3/main_application.cpp b/rpcs3/main_application.cpp index 8c067f3975..ce1f917059 100644 --- a/rpcs3/main_application.cpp +++ b/rpcs3/main_application.cpp @@ -2,7 +2,6 @@ #include "main_application.h" #include "display_sleep_control.h" #include "gamemode_control.h" -#include "rpcs3qt/gui_settings.h" #include "rpcs3qt/config_database.h" #include "util/types.hpp" @@ -418,8 +417,7 @@ EmuCallbacks main_application::CreateCallbacks() sys_log.notice("Trying to retrieve database config for: '%s'", title_id); - const auto settings = std::make_shared(); - config_database config_db(settings, nullptr); + config_database config_db(nullptr); config_db.request_config_database(false); if (!config_db.has_config(title_id)) diff --git a/rpcs3/rpcs3qt/config_database.cpp b/rpcs3/rpcs3qt/config_database.cpp index 7e26252d3f..6f8f4e8f60 100644 --- a/rpcs3/rpcs3qt/config_database.cpp +++ b/rpcs3/rpcs3qt/config_database.cpp @@ -6,17 +6,19 @@ LOG_CHANNEL(gui_log, "GUI"); -config_database::config_database(std::shared_ptr settings, QWidget* parent) +config_database::config_database(QWidget* parent) : QObject(parent) - , m_gui_settings(std::move(settings)) { - m_filepath = m_gui_settings->GetSettingsDir() + "/config_database.dat"; - m_downloader = new downloader(parent); + m_filepath = gui_settings::GetSettingsDir() + "config_database.dat"; request_config_database(); - connect(m_downloader, &downloader::signal_download_error, this, &config_database::handle_download_error); - connect(m_downloader, &downloader::signal_download_finished, this, &config_database::handle_download_finished); - connect(m_downloader, &downloader::signal_download_canceled, this, &config_database::handle_download_canceled); + if (parent) + { + m_downloader = new downloader(parent); + connect(m_downloader, &downloader::signal_download_error, this, &config_database::handle_download_error); + connect(m_downloader, &downloader::signal_download_finished, this, &config_database::handle_download_finished); + connect(m_downloader, &downloader::signal_download_canceled, this, &config_database::handle_download_canceled); + } } config_database::~config_database() @@ -89,7 +91,7 @@ void config_database::request_config_database(bool online) const std::string url = "https://api.rpcs3.net/config/?api=v1"; gui_log.notice("Beginning config database download from: %s", url); - m_downloader->start(url, true, true, true, tr("Downloading Config Database")); + ensure(m_downloader)->start(url, true, true, true, tr("Downloading Config Database")); Q_EMIT download_started(); } diff --git a/rpcs3/rpcs3qt/config_database.h b/rpcs3/rpcs3qt/config_database.h index e0283ddf7a..afdb091e5d 100644 --- a/rpcs3/rpcs3qt/config_database.h +++ b/rpcs3/rpcs3qt/config_database.h @@ -4,14 +4,13 @@ #include class downloader; -class gui_settings; class config_database : public QObject { Q_OBJECT public: - config_database(std::shared_ptr settings, QWidget* parent); + config_database(QWidget* parent); virtual ~config_database(); bool has_config(const std::string& title_id) const; @@ -35,7 +34,6 @@ private: /** Creates new set from the database. Returns config for the optional serial. */ std::optional read_json(const QByteArray& data, bool after_download, const std::string& serial = ""); - std::shared_ptr m_gui_settings; QString m_filepath; downloader* m_downloader = nullptr; diff --git a/rpcs3/rpcs3qt/game_compatibility.cpp b/rpcs3/rpcs3qt/game_compatibility.cpp index 7f408d39d3..0652de4268 100644 --- a/rpcs3/rpcs3qt/game_compatibility.cpp +++ b/rpcs3/rpcs3qt/game_compatibility.cpp @@ -13,17 +13,19 @@ LOG_CHANNEL(compat_log, "Compat"); -game_compatibility::game_compatibility(std::shared_ptr settings, QWidget* parent) +game_compatibility::game_compatibility(QWidget* parent) : QObject(parent) - , m_gui_settings(std::move(settings)) { - m_filepath = m_gui_settings->GetSettingsDir() + "/compat_database.dat"; - m_downloader = new downloader(parent); + m_filepath = gui_settings::GetSettingsDir() + "compat_database.dat"; RequestCompatibility(); - connect(m_downloader, &downloader::signal_download_error, this, &game_compatibility::handle_download_error); - connect(m_downloader, &downloader::signal_download_finished, this, &game_compatibility::handle_download_finished); - connect(m_downloader, &downloader::signal_download_canceled, this, &game_compatibility::handle_download_canceled); + if (parent) + { + m_downloader = new downloader(parent); + connect(m_downloader, &downloader::signal_download_error, this, &game_compatibility::handle_download_error); + connect(m_downloader, &downloader::signal_download_finished, this, &game_compatibility::handle_download_finished); + connect(m_downloader, &downloader::signal_download_canceled, this, &game_compatibility::handle_download_canceled); + } } void game_compatibility::handle_download_error(const QString& error) @@ -227,7 +229,7 @@ void game_compatibility::RequestCompatibility(bool online) const std::string url = "https://rpcs3.net/compatibility?api=v1&export"; compat_log.notice("Beginning compatibility database download from: %s", url); - m_downloader->start(url, true, true, true, tr("Downloading Database")); + ensure(m_downloader)->start(url, true, true, true, tr("Downloading Database")); // We want to retrieve a new database, therefore refresh game list and indicate that Q_EMIT DownloadStarted(); diff --git a/rpcs3/rpcs3qt/game_compatibility.h b/rpcs3/rpcs3qt/game_compatibility.h index 7c4d1a80a1..56d251097a 100644 --- a/rpcs3/rpcs3qt/game_compatibility.h +++ b/rpcs3/rpcs3qt/game_compatibility.h @@ -7,7 +7,6 @@ #include class downloader; -class gui_settings; namespace compat { @@ -120,29 +119,9 @@ class game_compatibility : public QObject { Q_OBJECT -private: - const std::map Status_Data = - { - { "Playable", { 0, "", "#1ebc61", tr("Playable"), tr("Games that can be properly played from start to finish") } }, - { "Ingame", { 1, "", "#f9b32f", tr("Ingame"), tr("Games that either can't be finished, have serious glitches or have insufficient performance") } }, - { "Intro", { 2, "", "#e08a1e", tr("Intro"), tr("Games that display image but don't make it past the menus") } }, - { "Loadable", { 3, "", "#e74c3c", tr("Loadable"), tr("Games that display a black screen with a framerate on the window's title") } }, - { "Nothing", { 4, "", "#455556", tr("Nothing"), tr("Games that don't initialize properly, not loading at all and/or crashing the emulator") } }, - { "NoResult", { 5, "", "", tr("No results found"), tr("There is no entry for this game or application in the compatibility database yet.") } }, - { "NoData", { 6, "", "", tr("Database missing"), tr("Right click here and download the current database.\nMake sure you are connected to the internet.") } }, - { "Download", { 7, "", "", tr("Retrieving..."), tr("Downloading the compatibility database. Please wait...") } } - }; - std::shared_ptr m_gui_settings; - QString m_filepath; - downloader* m_downloader = nullptr; - std::map m_compat_database; - - /** Creates new map from the database */ - bool handle_json(const QByteArray& data, bool after_download); - public: /** Handles reads, writes and downloads for the compatibility database */ - game_compatibility(std::shared_ptr settings, QWidget* parent); + game_compatibility(QWidget* parent); /** Reads database. If online set to true: Downloads and writes the database to file */ void RequestCompatibility(bool online = false); @@ -166,4 +145,23 @@ private Q_SLOTS: void handle_download_error(const QString& error); void handle_download_finished(const QByteArray& content); void handle_download_canceled(); + +private: + /** Creates new map from the database */ + bool handle_json(const QByteArray& data, bool after_download); + + const std::map Status_Data = + { + { "Playable", { 0, "", "#1ebc61", tr("Playable"), tr("Games that can be properly played from start to finish") } }, + { "Ingame", { 1, "", "#f9b32f", tr("Ingame"), tr("Games that either can't be finished, have serious glitches or have insufficient performance") } }, + { "Intro", { 2, "", "#e08a1e", tr("Intro"), tr("Games that display image but don't make it past the menus") } }, + { "Loadable", { 3, "", "#e74c3c", tr("Loadable"), tr("Games that display a black screen with a framerate on the window's title") } }, + { "Nothing", { 4, "", "#455556", tr("Nothing"), tr("Games that don't initialize properly, not loading at all and/or crashing the emulator") } }, + { "NoResult", { 5, "", "", tr("No results found"), tr("There is no entry for this game or application in the compatibility database yet.") } }, + { "NoData", { 6, "", "", tr("Database missing"), tr("Right click here and download the current database.\nMake sure you are connected to the internet.") } }, + { "Download", { 7, "", "", tr("Retrieving..."), tr("Downloading the compatibility database. Please wait...") } } + }; + QString m_filepath; + downloader* m_downloader = nullptr; + std::map m_compat_database; }; diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp index ca0affc585..32d36d7bd1 100644 --- a/rpcs3/rpcs3qt/game_list_frame.cpp +++ b/rpcs3/rpcs3qt/game_list_frame.cpp @@ -75,8 +75,8 @@ game_list_frame::game_list_frame(std::shared_ptr gui_settings, std m_game_list->verticalScrollBar()->installEventFilter(this); m_iso_integrity = new iso_integrity(this); - m_game_compat = new game_compatibility(m_gui_settings, this); - m_config_db = new config_database(m_gui_settings, this); + m_game_compat = new game_compatibility(this); + m_config_db = new config_database(this); m_central_widget = new QStackedWidget(this); m_central_widget->addWidget(m_game_list); diff --git a/rpcs3/rpcs3qt/gui_settings.cpp b/rpcs3/rpcs3qt/gui_settings.cpp index fdbab7345e..4d72b74a70 100644 --- a/rpcs3/rpcs3qt/gui_settings.cpp +++ b/rpcs3/rpcs3qt/gui_settings.cpp @@ -106,7 +106,7 @@ namespace gui gui_settings::gui_settings(QObject* parent) : settings(parent) { - m_settings = std::make_unique(ComputeSettingsDir() + gui::Settings + ".ini", QSettings::Format::IniFormat, parent); + m_settings = std::make_unique(GetSettingsDir() + gui::Settings + ".ini", QSettings::Format::IniFormat, parent); } QStringList gui_settings::GetGameListCategoryFilters(bool is_list_mode) const @@ -307,7 +307,7 @@ QColor gui_settings::GetCustomColor(int col) const QStringList gui_settings::GetStylesheetEntries() const { const QStringList name_filter = QStringList("*.qss"); - QStringList res = gui::utils::get_dir_entries(m_settings_dir, name_filter); + QStringList res = gui::utils::get_dir_entries(QDir(GetSettingsDir()), name_filter); #if !defined(_WIN32) // Makes stylesheets load if using AppImage (App Bundle) or installed to /usr/bin #ifdef __APPLE__ diff --git a/rpcs3/rpcs3qt/persistent_settings.cpp b/rpcs3/rpcs3qt/persistent_settings.cpp index c18f8a1a1d..59f476198d 100644 --- a/rpcs3/rpcs3qt/persistent_settings.cpp +++ b/rpcs3/rpcs3qt/persistent_settings.cpp @@ -8,7 +8,7 @@ LOG_CHANNEL(cfg_log, "CFG"); persistent_settings::persistent_settings(QObject* parent) : settings(parent) { // Don't use the .ini file ending for now, as it will be confused for a regular gui_settings file. - m_settings = std::make_unique(ComputeSettingsDir() + gui::persistent::persistent_file_name + ".dat", QSettings::Format::IniFormat, parent); + m_settings = std::make_unique(GetSettingsDir() + gui::persistent::persistent_file_name + ".dat", QSettings::Format::IniFormat, parent); } void persistent_settings::SetPlaytime(const QString& serial, quint64 playtime, bool sync) diff --git a/rpcs3/rpcs3qt/qt_utils.cpp b/rpcs3/rpcs3qt/qt_utils.cpp index fe7bb6f8d6..7ef0317ec2 100644 --- a/rpcs3/rpcs3qt/qt_utils.cpp +++ b/rpcs3/rpcs3qt/qt_utils.cpp @@ -166,7 +166,7 @@ namespace gui QStringList get_dir_entries(const QDir& dir, const QStringList& name_filters, bool full_path) { - QFileInfoList entries = dir.entryInfoList(name_filters, QDir::Files); + const QFileInfoList entries = dir.entryInfoList(name_filters, QDir::Files); QStringList res; for (const QFileInfo& entry : entries) { diff --git a/rpcs3/rpcs3qt/settings.cpp b/rpcs3/rpcs3qt/settings.cpp index c87918d468..a57c0d7f68 100644 --- a/rpcs3/rpcs3qt/settings.cpp +++ b/rpcs3/rpcs3qt/settings.cpp @@ -2,8 +2,7 @@ #include "Utilities/File.h" -settings::settings(QObject* parent) : QObject(parent), - m_settings_dir(ComputeSettingsDir()) +settings::settings(QObject* parent) : QObject(parent) { } @@ -20,12 +19,7 @@ void settings::sync() } } -QString settings::GetSettingsDir() const -{ - return m_settings_dir.absolutePath(); -} - -QString settings::ComputeSettingsDir() +QString settings::GetSettingsDir() { return QString::fromStdString(fs::get_config_dir()) + "/GuiConfigs/"; } diff --git a/rpcs3/rpcs3qt/settings.h b/rpcs3/rpcs3qt/settings.h index 8a7069d884..2f25b9cbb2 100644 --- a/rpcs3/rpcs3qt/settings.h +++ b/rpcs3/rpcs3qt/settings.h @@ -31,7 +31,7 @@ public: void sync(); - QString GetSettingsDir() const; + static QString GetSettingsDir(); QVariant GetValue(const QString& key, const QString& name, const QVariant& def) const; QVariant GetValue(const gui_save& entry) const; @@ -49,8 +49,5 @@ public Q_SLOTS: void SetValue(const QString& key, const QString& name, const QVariant& value, bool sync = true) const; protected: - static QString ComputeSettingsDir(); - std::unique_ptr m_settings; - QDir m_settings_dir; };