Widget component doesn't unregister its virtual window, causing a memory leak

Hi,

I noticed in our project that our used slate memory was going up when switching between levels. After some careful analysis of memory traces, I noticed widget components consistently being mentioned. Some debugging later, and I discovered why: the widget component doesn’t clean up its virtual window properly under several circumstances.

For some reason, RemoveWidgetFromScreen invalidates the SlateWindow shared pointer, without actually unregistering the virtual window inside it. Because of this, whenever the component is destroyed, the code that is supposed to clean up the window can’t, because the pointer is gone.

void UWidgetComponent::RemoveWidgetFromScreen()
{
#if !UE_SERVER
  if (!IsRunningDedicatedServer())
  {
    if(SlateWindow != nullptr)
    {
      ResetWorldUserFocusOnWidget();

      if(GetWidgetSpace() == EWidgetSpace::World)
      {
        SlateWindow->SetContent(SNullWidget::NullWidget);
      }

      SlateWindow.Reset();
    }

Several other places call RemoveWidgetFromScreen and so they may leak the virtual window, for example:

  • Setting the widget manually, both with a slate widget and a UMG Widget
  • Setting the widget’s owning local player
  • Whenever the widget is added to the screen? This one is a bit weird, but the UpdateWidgetOnScreen function has a call to it.

Does a fix or workaround for this exist? While the leak isn’t that big, it does accumulate over time, and makes profiling memory for other aspects of the project more difficult.

Thanks in advance.

[Attachment Removed]

Steps to Reproduce

  1. Put some widget components in some levels
  2. While in -game mode, switch between the levels.
  3. Observe the UI Slate memory going up.
    [Attachment Removed]

Here’s the test project

[Attachment Removed]

Hi,

Thanks for the report and repro project! We should be able to just call UnregisterWindow instead of resetting the pointer here, looks to be sufficient to stop the leak in your project. I’ll get that checked in.

Best,

Cody

[Attachment Removed]

This is checked into UE6 main now at CL#58524394. Thanks again!

[Attachment Removed]