String in Reference memory leak

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By aleeeeee

Hi, I’ve been having issues with memory leaks in my program. I have boiled it down to this simple reproduction script:

extends Node

class StringContainer extends Reference:
	var string: String = "";

func test_memory_leak():
	var cs = [];
	for i in range(1024):
		for q in range(256):
			var nm := str(i).repeat(64) + str(q);
			var c = StringContainer.new();
			c.string = nm;
			cs.append(c);
			
		yield(get_tree(), "idle_frame");
	
	cs.clear();
	
	print("Cleared cs");


func _ready():
	test_memory_leak();

A bunch of StringContainer objects get added to the array cs, then cs gets cleared. Since StringContainer extends Reference, clearing cs should dereference all of the StringContainers, freeing the memory used.

The in-engine memory monitor suggests that this is happening correctly:
enter image description here

However, the memory monitor suggests otherwise; the memory use stays at around 580.2MiB at the end and never drops.
enter image description here

This doesn’t happen if I replace cs.append(c); with cs.append(nm);, the memory use grows and then drops back to <60MiB as expected.

How can I avoid this memory leak while storing the string within a class?

:bust_in_silhouette: Reply From: Lola

Hello,

I don’t have any knowledge of OS memory managment, but I think those 580 MiBs are somewhat ‘reserved’ for your app at this point in execution.

By adding

yield(get_tree().create_timer(5.0), "timeout")
print("Repeating the whole thing...")
test_memory_leak()

at the end of your test_memory_leak function you will notice that although godot’s monitors will report new memory usage, the reported memory usage by your task manager won’t change.

I have no idea why the behavior changes depending on class usage or not though.