godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91k stars 21.17k forks source link

Circular script preloading causes leak without warning (both with preload or named classes) #16959

Open Zylann opened 6 years ago

Zylann commented 6 years ago

Godot 2.1.5 beta, Godot 2.1.4, Windows 10 64 bits

I found out my project had a circular dependency between two scripts which were preloading each other into a const (though the game has worked perfectly fine so far, it's been a year). The use case was only to use extends on it. Workaround is to use load...

The result of this is a random memory leak (which doesn't always happen) and two cryptic errors:

ERROR: SelfList<class GDFunction>::List::~List: Condition ' _first != 0 ' is true.
   At: core\self_list.h:80
ERROR: SelfList<class GDScript>::List::~List: Condition ' _first != 0 ' is true.
   At: core\self_list.h:80
WARNING: ObjectDB::cleanup: ObjectDB Instances still exist!
     At: core\object.cpp:1845
ERROR: ResourceCache::clear: Resources Still in use at Exit!
   At: core\resource.cpp:378

Reproduction project; CircularScriptPreload.zip

Ranoller commented 6 years ago

Are you using some module?

Zylann commented 6 years ago

@Ranoller no, just official Godot 2.1.4.

Ranoller commented 6 years ago

No idea then... DragonBones module gives to me ObjectDB Instances still exist! on app exit, but only on exit (and i´m going to report that right now)

Zylann commented 6 years ago

To me it's quite obvious: there is a circular reference. Now I'm not sure if that's really intented to produce one or not. If it is, would be nice to show a warning when the resource gets loaded.

Ranoller commented 6 years ago

No error until close with your test. On quit there are the 2 first mensagges (GDFunction and GDScript). Last two messages aren´t printed.

Ranoller commented 6 years ago

Second time that executes the four messages are printed.

Zylann commented 6 years ago

@Ranoller it's random :p

Geequlim commented 6 years ago

Related to #15839

akien-mga commented 6 years ago

According to https://github.com/godotengine/godot/issues/15839#issuecomment-358632016:

This is not a bug, this is a feature. It's in the GDScript documentation. Any cycles are leaked.

KoBeWi commented 6 years ago

Uh, I have the same issue, but I don't know what is causing it. I'm not using cyclic preloading anywhere (at least not intentionally) and the issue seems to appear only in exported project. Is there a way to trace the problem? I'm using Godot 3.0.2

Zylann commented 6 years ago

@KoBeWi what is your complete log of errors? The one about the leak can be caused by many things, not just cyclic refs

KoBeWi commented 6 years ago

It's the same as here, but with different line numbers (probably because of Godot version):

ERROR: SelfList::List::~List: Condition ' _first != 0 ' is true. At: c:\projects\godot-builds\godot\core\self_list.h:100 ERROR: SelfList::List::~List: Condition ' _first != 0 ' is true. At: c:\projects\godot-builds\godot\core\self_list.h:100 WARNING: ObjectDB::cleanup: ObjectDB Instances still exist! At: core\object.cpp:1989 ERROR: ResourceCache::clear: Resources Still in use at Exit! At: core\resource.cpp:418

KoBeWi commented 5 years ago

Looks like in 3.1 you are prevented from circular preloading: E 0:00:00:0683 Resource: 'res://new_script.gd' is already being loaded. Cyclic reference?

akien-mga commented 3 years ago

I can confirm the issue in 3.2.4 RC 1, and it happens with class_name too when you reference the current class in itself, e.g.:

extends Node
class_name MyNode

var test : MyNode = null

It appears to be fixed in master, but a fix for 3.2 would still be very welcome.

Related to / partial duplicate of #21461.