+3 votes

I call "node.free()", but if only the node is freed, it throws an error
"Attempt to call function 'free' in base 'previously freed instance' on a null instance."

How do I know if the node is deleted ? It shows "[Deleted Object]" when I use "print(node)" ,

asked Nov 21, 2016 in Engine by Kevin (76 points)

Keep in mind that there is the functionqueue_free that will solve that problem in many cases.

But I have tried "queue_free", it doesn't work.

That's why I said "in many cases". It can only solve the problem if you aren't keeping and using a reference to the freed node yourself.
If you are re-acquiring it every time queue_free() should make sure that you can't find a node that isn't valid anymore.

(Which is not to say that this was a better solution in every case, it's just something to keep in mind.)

2 Answers

+8 votes
var wr = weakref(node)
if (!wr.get_ref()):
    # freed
else:
    # not freed
answered Nov 21, 2016 by volzhs (9,320 points)

it works great!!!thanks

This feels very wrong to me, as it seems to be a relying on an unreliable runtime safety check. What if another node took place of the deleted node in memory? Then I would assume get_ref would still succeed, and the OP would free a different node that is not the intended target. I don't know Godot's design well enough to be sure, but I don't understand how it can provide reliable information about a deleted node without keeping a history of all deleted nodes, which I'm sure Godot is not doing (at least not in exported code, as the code would then consume all available memory over time and run out of memory). Maybe I'm missing something here. One should keep track of whether a node has been freed via other means, and not attempt to do any operation a freed node (and that includes weakref). If someone who knows Godot's design better could chime in, that would be great.

By the way, this should work if the weakref was created before there was any chance the node was freed. That should be clearly specified in the answer though, as I can't see how the code would work reliably the way it's written.

Heh, I can tell you come from the land of C and know a bit about malloc. Remember, gdscript is a scripting language. An object never dies unless there are no more references to that object, this is a mandatory requirement. So, being able to even call weakref, means that "node" still exists in some sense of the word. You may have done "node = k", and some other thread called "k.deallocate(); k = null", but that other thread can't make you lose the validity of "node" as an object, because that would violate the idea of a scripting a language. The main idea here, is that "node"/"k" will likely only contain an object_id, and then a pointer to the rest of the data. that pointer will be set to null "k.deallocate" is called, so that now "node" refers to a "deallocated node", but it still "exists", just as lonely null pointer and its old objectid. And, the 8 bytes used to keep track of the obj_id and the pointer will be deallocated whenever the variable "node" gets updated to reference something else, and the garbage collector cleans it up because neither "node" nor "k" reference it anymore. Regardless of weakref, it would be unacceptable to call some function on a node and then it magically calls the function on a different node instead because the node was deallocated and then reallocated. In summary, "node.queuefree()" will make the node and invalid node, but not destroy it completely.

+6 votes

As of Godot 3.1, you can use:

is_instance_valid(node)
answered Jun 3, 2019 by kiwibonga (28 points)

Thank you this is exactly what i was looking for

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.