From 207253d67cdef67235805d595999fa0a2e4fcbd9 Mon Sep 17 00:00:00 2001 From: Prince Ozordi Date: Sun, 4 Jan 2026 23:28:08 -0400 Subject: [PATCH] Fix memory leak: remove static from local variables in Recompile() Three local variables in recompiler.cpp were declared as 'static', causing unbounded memory growth during recompilation of large executables: - Line 2291: std::unordered_set labels - Line 2397: std::string tempString - Line 2645: std::vector temp Problem: Static local variables persist across function calls and their containers (string, vector, unordered_set) only grow - they never shrink. When recompiling large games with 50,000+ functions: 1. 'tempString' accumulates ALL generated C++ code across every function 2. 'labels' accumulates all label addresses from every function 3. 'temp' accumulates file comparison buffers This was discovered while recompiling GTA IV (~18MB code, ~50k functions). The process consumed 300GB+ RAM and crashed the server after 4 hours. Why it wasn't caught earlier: - Sonic Unleashed (the original target) is smaller - Most test machines have enough RAM to complete before OOM - The static keyword was likely intended as a micro-optimization to avoid repeated allocations, but std::string/vector capacity only increases Fix: Remove 'static' keyword so variables are properly deallocated after each function is processed. Memory usage now stays under 2GB for GTA IV. Tested: Successfully recompiled GTA IV without memory issues. --- XenonRecomp/recompiler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/XenonRecomp/recompiler.cpp b/XenonRecomp/recompiler.cpp index fa91527..df79a13 100644 --- a/XenonRecomp/recompiler.cpp +++ b/XenonRecomp/recompiler.cpp @@ -2288,7 +2288,7 @@ bool Recompiler::Recompile(const Function& fn) auto end = base + fn.size; auto* data = (uint32_t*)image.Find(base); - static std::unordered_set labels; + std::unordered_set labels; labels.clear(); for (size_t addr = base; addr < end; addr += 4) @@ -2394,7 +2394,7 @@ bool Recompiler::Recompile(const Function& fn) // TODO: the printing scheme here is scuffed RecompilerLocalVariables localVariables; - static std::string tempString; + std::string tempString; tempString.clear(); std::swap(out, tempString); @@ -2642,7 +2642,7 @@ void Recompiler::SaveCurrentOutData(const std::string_view& name) FILE* f = fopen(filePath.c_str(), "rb"); if (f) { - static std::vector temp; + std::vector temp; fseek(f, 0, SEEK_END); long fileSize = ftell(f);