From 2f86f95c3f79681437e191f3d9c5365f9d0fd2ac Mon Sep 17 00:00:00 2001 From: Elad <18193363+elad335@users.noreply.github.com> Date: Wed, 22 Oct 2025 07:49:35 +0300 Subject: [PATCH] vm: Deallocate memory early, check no PS3 memory leaks --- rpcs3/Emu/Cell/SPUDisAsm.cpp | 2 +- rpcs3/Emu/Memory/vm.cpp | 19 ++++++++++++++++++- rpcs3/rpcs3qt/debugger_frame.cpp | 3 +++ rpcs3/rpcs3qt/memory_viewer_panel.cpp | 11 ++++++++++- rpcs3/rpcs3qt/memory_viewer_panel.h | 6 ++++-- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUDisAsm.cpp b/rpcs3/Emu/Cell/SPUDisAsm.cpp index 645a79969f..9529babb41 100644 --- a/rpcs3/Emu/Cell/SPUDisAsm.cpp +++ b/rpcs3/Emu/Cell/SPUDisAsm.cpp @@ -15,7 +15,7 @@ u32 SPUDisAsm::disasm(u32 pc) { last_opcode.clear(); - if (pc < m_start_pc || pc >= SPU_LS_SIZE) + if (!m_shm || pc < m_start_pc || pc >= SPU_LS_SIZE) { return 0; } diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index a3c98dabbc..5441176d6a 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -1329,6 +1329,16 @@ namespace vm std::vector> event_data; ensure(size == _page_unmap(it->first, size, this->flags, it->second.second.get(), unmapped ? *unmapped : event_data)); + if (it->second.second && addr < 0xE0000000) + { + if (it->second.second.use_count() != 1) + { + fmt::throw_exception("External memory usage at block 0x%x (addr=0x%x, size=0x%x)", this->addr, it->first, size); + } + + it->second.second.reset(); + } + it = next; } @@ -1338,6 +1348,8 @@ namespace vm #ifdef _WIN32 m_common->unmap_critical(vm::get_super_ptr(addr)); #endif + ensure(m_common.use_count() == 1); + m_common.reset(); } return true; @@ -1349,6 +1361,7 @@ namespace vm block_t::~block_t() { ensure(!is_valid()); + ensure(!m_common || m_common.use_count() == 1); } u32 block_t::alloc(const u32 orig_size, const std::shared_ptr* src, u32 align, u64 flags) @@ -2244,7 +2257,11 @@ namespace vm for (auto& block : g_locations) { - if (block) _unmap_block(block); + if (block) + { + _unmap_block(block); + ensure(block.use_count() == 1); + } } g_locations.clear(); diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp index b85aa2859e..8eb4bce3fa 100644 --- a/rpcs3/rpcs3qt/debugger_frame.cpp +++ b/rpcs3/rpcs3qt/debugger_frame.cpp @@ -241,6 +241,9 @@ void debugger_frame::closeEvent(QCloseEvent* event) QDockWidget::closeEvent(event); Q_EMIT DebugFrameClosed(); + + m_spu_disasm_memory.reset(); + m_cpu.reset(); } void debugger_frame::showEvent(QShowEvent* event) diff --git a/rpcs3/rpcs3qt/memory_viewer_panel.cpp b/rpcs3/rpcs3qt/memory_viewer_panel.cpp index 533dccc4d2..951ff41087 100644 --- a/rpcs3/rpcs3qt/memory_viewer_panel.cpp +++ b/rpcs3/rpcs3qt/memory_viewer_panel.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -732,7 +733,7 @@ void* memory_viewer_panel::to_ptr(u32 addr, u32 size) const } case thread_class::spu: { - if (size <= SPU_LS_SIZE && SPU_LS_SIZE - size >= (addr % SPU_LS_SIZE)) + if (m_spu_shm && size <= SPU_LS_SIZE && SPU_LS_SIZE - size >= (addr % SPU_LS_SIZE)) { return m_spu_shm->map_self() + (addr % SPU_LS_SIZE); } @@ -961,6 +962,14 @@ void memory_viewer_panel::keyPressEvent(QKeyEvent* event) QDialog::keyPressEvent(event); } +void memory_viewer_panel::closeEvent(QCloseEvent* event) +{ + event->accept(); + m_spu_shm.reset(); + m_disasm.reset(); + m_get_cpu = [](){ return std::add_pointer_t{}; }; +} + void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format format, u32 width, u32 height, bool flipv) const { u32 texel_bytes = 4; diff --git a/rpcs3/rpcs3qt/memory_viewer_panel.h b/rpcs3/rpcs3qt/memory_viewer_panel.h index 756323be97..935560cc2a 100644 --- a/rpcs3/rpcs3qt/memory_viewer_panel.h +++ b/rpcs3/rpcs3qt/memory_viewer_panel.h @@ -19,6 +19,7 @@ class QLabel; class QThread; class QHBoxLayout; class QKeyEvent; +class QCloseEvent; class cpu_thread; class CPUDisAsm; @@ -95,10 +96,10 @@ private: QHBoxLayout* m_hbox_mem_panel = nullptr; QThread* m_search_thread = nullptr; - const std::function m_get_cpu; + std::function m_get_cpu; const thread_class m_type; const std::add_pointer_t m_rsx; - const std::shared_ptr m_spu_shm; + std::shared_ptr m_spu_shm; const u32 m_addr_mask; std::shared_ptr m_disasm; @@ -119,6 +120,7 @@ private: u64 OnSearch(std::string wstr, u32 mode); void keyPressEvent(QKeyEvent* event) override; + void closeEvent(QCloseEvent* event) override; }; // Lifetime management with IDM