godotengine / godot-docs

Godot Engine official documentation
https://docs.godotengine.org
Other
3.94k stars 3.22k forks source link

Explain Orphan nodes and leaking memory #2854

Open qarmin opened 5 years ago

qarmin commented 5 years ago

Probably a lot of people doesn't know that a game can leaking memory. The simplest method to check leak is to look at the "Orphan nodes" monitor, which should always show 0, when no leaked instance of node was found. Also they should know that this message from console is about leaking memory:

ERROR: ~List: Condition ' _first != __null ' is true.
   At: ./core/self_list.h:111
ERROR: ~List: Condition ' _first != __null ' is true.
   At: ./core/self_list.h:111
WARNING: cleanup: ObjectDB Instances still exist!
     At: core/object.cpp:2095

and it can be easily better described by adding -v to godot run parameters(godot -e -v)

ERROR: ~List: Condition ' _first != __null ' is true.
   At: ./core/self_list.h:111.
ERROR: ~List: Condition ' _first != __null ' is true.
   At: ./core/self_list.h:111.
WARNING: cleanup: ObjectDB Instances still exist!
   At: core/object.cpp:2098.
Leaked instance: GDScript:1148 - Resource name:  Path: 
Leaked instance: GDScriptNativeClass:540
Orphan StringName: Reference
Orphan StringName: causes_error
Orphan StringName: new
Orphan StringName: GDScriptNativeClass
Orphan StringName: val
Orphan StringName: res://main_scene.gd
Orphan StringName: from_string
Orphan StringName: input
Orphan StringName: _init
Orphan StringName: GDScript
StringName: 10 unclaimed string names at exit.

Also I will add informations, that resources doesn't must be deleted manually because they are removed when last node stops use it.

Screenshot_20191014_082029

ivanzamoraarias commented 4 years ago

Okay this is happening to me whenever I run it on terminal, it is frustrating when running on continuous integration as Jenkings, so tests wont pass (-_-) , is there a work around ?

Calinou commented 4 years ago

@ivanzamoraarias As far as I know, leaked instances don't affect Godot's exit code.

ivanzamoraarias commented 4 years ago

well for me everytime I send -gexit , the same error appears , no metter what. ._.

frob commented 3 years ago

@ivanzamoraarias This might be because of the way gut works in v7. I am just getting into it now but I think we have to do more manual memory management in our tests. https://github.com/bitwes/Gut/wiki/Memory-Management

Yesyoor commented 3 years ago

I tracked down the memory leaks of my code and it seems to be a bug in Godot. Declaring an instance variable of a class - which inherited node2d in my case - and instancing it with an other class, lead to memory leaks, although I freed that variable, example:

I have a custom scene called Module.tscn, holding the script module.gd

module.gd extends Node2D class_name Module var edgeClass = preload("res://Szenen/EdgeLine.tscn") var knodeClass = preload("res://Szenen/Knode.tscn") var drag = false export (PackedScene) var leftKnode = null export (PackedScene) var rightKnode = null export (PackedScene) var myEdge = edgeClass.instance() export var isVertical : bool =false var turned : int =0 ... The variable ''myEdge" holds an instance of the Edge.tscn scene which has a script "edge.gd" attached on it. When creating new instances of Modul.tscn memory was leaked every single time, although I called myEdge.queue_free() and debugging it showed that myEdge disappeared. The memory leaks occurred when instancing Modul.tscn, so I instanced it in a custom my_init() function and the memory leaks disappeared:

module.gd extends Node2D class_name Module var edgeClass = preload("res://Szenen/EdgeLine.tscn") var knodeClass = preload("res://Szenen/Knode.tscn") var drag = false export (PackedScene) var leftKnode = null export (PackedScene) var rightKnode = null export (PackedScene) var myEdge export var isVertical : bool =false var turned :int =0

func my_init(): myEdge = edgeClass.instance()

I think it should be reported as a bug, or am I missing something? I am pretty sure that it should not make any difference where I instance that variable, but it did