Please confirm the following points:
Affected Project
libprojectM (including the playlist library)
Affected Version
4.1.6
Operating Systems and Architectures
Windows (x64)
Build Tools
Compiler: Microsoft Windows SDK
Additional Project, OS and Toolset Details
No response
Type of Defect
Specific bug in projectM code (please link the code in question)
Log Output
Describe the Issue
Summary
Memory leak identified in libprojectM 4.1.6 during continuous playlist-driven preset transitions on Windows. Memory usage climbs linearly from an 80MB baseline to over 1.2GB within a 7-8 hour window.
Environment
Library Version: libprojectM v4.1.6 Core Release
Operating System: Windows 11 x64
IDE / Toolchain: Visual Studio 2026 / MSVC Compiler
How to Reproduce
The leak occurs when disabling projectM's internal auto-transitioning and driving preset switches authoritatively from the application layer using a Win32 timer:
Instantiate the engine and immediately lock preset switching:
projectm_set_preset_locked(m_pProjectM, true);
Set up a standard Win32 WM_TIMER callback.
Every interval (e.g., matching preset durations), manually call:
projectm_playlist_play_next(m_pProjectM, false);
Observe memory usage over time via Task Manager or Diagnostic Tools.
Visual Studio Diagnostic Profiler Evidence
A heap snapshot differential taken between preset transition cycles reveals that while parent container structures are torn down, primitive array allocations inside the renderer namespace accumulate indefinitely on the process heap.
Here is the raw data dump from the Visual Studio 2026 Memory Profiler Diff (sorted by size impact):
void 4094 93016
projectM-4d.dll!libprojectM::Renderer::Color[] 10 84811
projectM-4d.dll!libprojectM::Renderer::Point[] 18 52042
char[] 172 20327
unsigned int[] 4 16007
projectM-4d.dll!libprojectM::MilkdropPreset::MilkdropPreset 1 15632
projectM-4d.dll!M4::HLSLTree::NodePage 2 8208
projectM-4d.dll!libprojectM::Renderer::TextureUV[] 3 6255
projectM-4d.dll!libprojectM::MilkdropPreset::CustomShape 4 5920
projectM-4d.dll!libprojectM::MilkdropPreset::CustomWaveform 4 5440
projectM-4d.dll!std::_Container_proxy 173 2768
projectM-4d.dll!libprojectM::MilkdropPreset::MilkdropShader 2 1840
char *[] 1 1464
projectM-4d.dll!std::_Ref_count_obj2libprojectM::Renderer::Texture 11 1056
projectM-4d.dll!M4::HLSLMacro *[] 1 736
projectM-4d.dll!std::_Tree_node<std::pair<unsigned int const ,std::shared_ptrlibprojectM::Renderer::TextureAttachment >,void *> 8 448
projectM-4d.dll!std::_Tree_node<std::pair<int const ,std::map<unsigned int,std::shared_ptrlibprojectM::Renderer::TextureAttachment,std::less,std::allocator<std::pair<unsigned int const ,std::shared_ptrlibprojectM::Renderer::TextureAttachment > > > >,void *> 7 448
projectM-4d.dll!std::_Tree_node<std::basic_string<char,std::char_traits,std::allocator >,void *> 4 288
projectM-4d.dll!std::_Ref_count_obj2libprojectM::Renderer::TextureAttachment 5 280
projectM-4d.dll!libprojectM::Renderer::TextureSamplerDescriptor 2 240
projectM-4d.dll!std::_Tree_node<std::pair<int const ,libprojectM::Renderer::TextureSamplerDescriptor>,void *> 1 160
projectM-4d.dll!std::_Tree_node<std::pair<M4::matrixCtor const ,std::basic_string<char,std::char_traits,std::allocator > >,void *> 1 112
projectM-4d.dll!std::_Ref_count_obj2libprojectM::Renderer::Sampler 2 64
bool *[] 1 64
projectM-4-playlistd.dll!std::_List_node<unsigned int,void *> 1 24
projectM-4-playlistd.dll!std::_Container_proxy 1 16
bool[] 1 16
unsigned int 2 8
char 1 1
Technical Observation
The numbers indicate a clear structural correlation. For every single new MilkdropPreset initialized, the system accumulates a matching set of CustomShape (+4) and CustomWaveform (+4) allocations.
Crucially, the raw vertex-drawing arrays associated with them (Color[] and Point[]) are left abandoned on the heap with positive count deltas. This confirms that while the parent objects are tracked, their low-level heap arrays lack a matching delete[] invocation during the transition sequence.
Technical Analysis
Since ~CustomShape() inside CustomShape.hpp is properly declared as a defaulted virtual destructor (virtual ~CustomShape() = default;), the parent wrapper object drops correctly.
However, the raw coordinate and color arrays (Color[], Point[]) used to instantiate the meshes for waveforms and shape elements are persisting on the system heap. This suggests that during a manual track change, the rendering pipeline misses an explicit array deallocation step (delete[]) or drops pointers before freeing the underlying memory boundaries of the active shader canvas elements.
Please confirm the following points:
Affected Project
libprojectM (including the playlist library)
Affected Version
4.1.6
Operating Systems and Architectures
Windows (x64)
Build Tools
Compiler: Microsoft Windows SDK
Additional Project, OS and Toolset Details
No response
Type of Defect
Specific bug in projectM code (please link the code in question)
Log Output
Describe the Issue
Summary
Memory leak identified in libprojectM 4.1.6 during continuous playlist-driven preset transitions on Windows. Memory usage climbs linearly from an 80MB baseline to over 1.2GB within a 7-8 hour window.
Environment
Library Version: libprojectM v4.1.6 Core Release
Operating System: Windows 11 x64
IDE / Toolchain: Visual Studio 2026 / MSVC Compiler
How to Reproduce
The leak occurs when disabling projectM's internal auto-transitioning and driving preset switches authoritatively from the application layer using a Win32 timer:
Instantiate the engine and immediately lock preset switching:
projectm_set_preset_locked(m_pProjectM, true);
Set up a standard Win32 WM_TIMER callback.
Every interval (e.g., matching preset durations), manually call:
projectm_playlist_play_next(m_pProjectM, false);
Observe memory usage over time via Task Manager or Diagnostic Tools.
Visual Studio Diagnostic Profiler Evidence
A heap snapshot differential taken between preset transition cycles reveals that while parent container structures are torn down, primitive array allocations inside the renderer namespace accumulate indefinitely on the process heap.
Here is the raw data dump from the Visual Studio 2026 Memory Profiler Diff (sorted by size impact):
void 4094 93016
projectM-4d.dll!libprojectM::Renderer::Color[] 10 84811
projectM-4d.dll!libprojectM::Renderer::Point[] 18 52042
char[] 172 20327
unsigned int[] 4 16007
projectM-4d.dll!libprojectM::MilkdropPreset::MilkdropPreset 1 15632
projectM-4d.dll!M4::HLSLTree::NodePage 2 8208
projectM-4d.dll!libprojectM::Renderer::TextureUV[] 3 6255
projectM-4d.dll!libprojectM::MilkdropPreset::CustomShape 4 5920
projectM-4d.dll!libprojectM::MilkdropPreset::CustomWaveform 4 5440
projectM-4d.dll!std::_Container_proxy 173 2768
projectM-4d.dll!libprojectM::MilkdropPreset::MilkdropShader 2 1840
char *[] 1 1464
projectM-4d.dll!std::_Ref_count_obj2libprojectM::Renderer::Texture 11 1056
projectM-4d.dll!M4::HLSLMacro *[] 1 736
projectM-4d.dll!std::_Tree_node<std::pair<unsigned int const ,std::shared_ptrlibprojectM::Renderer::TextureAttachment >,void *> 8 448
projectM-4d.dll!std::_Tree_node<std::pair<int const ,std::map<unsigned int,std::shared_ptrlibprojectM::Renderer::TextureAttachment,std::less,std::allocator<std::pair<unsigned int const ,std::shared_ptrlibprojectM::Renderer::TextureAttachment > > > >,void *> 7 448
projectM-4d.dll!std::_Tree_node<std::basic_string<char,std::char_traits,std::allocator >,void *> 4 288
projectM-4d.dll!std::_Ref_count_obj2libprojectM::Renderer::TextureAttachment 5 280
projectM-4d.dll!libprojectM::Renderer::TextureSamplerDescriptor 2 240
projectM-4d.dll!std::_Tree_node<std::pair<int const ,libprojectM::Renderer::TextureSamplerDescriptor>,void *> 1 160
projectM-4d.dll!std::_Tree_node<std::pair<M4::matrixCtor const ,std::basic_string<char,std::char_traits,std::allocator > >,void *> 1 112
projectM-4d.dll!std::_Ref_count_obj2libprojectM::Renderer::Sampler 2 64
bool *[] 1 64
projectM-4-playlistd.dll!std::_List_node<unsigned int,void *> 1 24
projectM-4-playlistd.dll!std::_Container_proxy 1 16
bool[] 1 16
unsigned int 2 8
char 1 1
Technical Observation
The numbers indicate a clear structural correlation. For every single new MilkdropPreset initialized, the system accumulates a matching set of CustomShape (+4) and CustomWaveform (+4) allocations.
Crucially, the raw vertex-drawing arrays associated with them (Color[] and Point[]) are left abandoned on the heap with positive count deltas. This confirms that while the parent objects are tracked, their low-level heap arrays lack a matching delete[] invocation during the transition sequence.
Technical Analysis
Since ~CustomShape() inside CustomShape.hpp is properly declared as a defaulted virtual destructor (virtual ~CustomShape() = default;), the parent wrapper object drops correctly.
However, the raw coordinate and color arrays (Color[], Point[]) used to instantiate the meshes for waveforms and shape elements are persisting on the system heap. This suggests that during a manual track change, the rendering pipeline misses an explicit array deallocation step (delete[]) or drops pointers before freeing the underlying memory boundaries of the active shader canvas elements.