I’m pretty sure that scripts were supposed to stop running when :Destroy()ed or parented to nil. Am I comepletely mistaken, or is this the desired behavior?
For reference, just set a script’s parent to nil or destroy it on the first line. All the following code executes.
Some devs parent scripts to nil on purpose as a tactic for exploit prevention. So changing this to a thing that disabled/destroys the script would probably break a ton of games out there.
The garbage collector (from what I understand) is made to clean up variables and objects (including roblox userdatas) that aren’t accessible from within Lua anymore from memory. With that in mind, it probably wont touch your scripts in nil since they’re actively running.
do
local lol = true -- lol only exists within the memory of this do block. If you try to access it outside the block, it doesn't exist.
end
-- The garbage collector will clear lol from memory once all the code is run.
Mhm. Although it should be noted that the lua garbage collector isn’t actively running. As in, it may take some time for HeheXD to actually be removed from memory, after being set to nil. You can prompt it run a cycle anytime though with collectgarbage().
Parenting a script to nil is not very useful as exploit prevention tactic as the code is still available with some effort (exploiters can read it from nil). Also I think since stacktrace has to remain available and the scripts having possible references to non-Lua parts of the engine, it is too difficult to determine when code is entirely without references and gc-able, thus scripts are never gc’d as precaution. Correct me if I am wrong, @Rerumu
Don’t forget that it is possible to leak memory on Roblox even with garbage collection:
do
local part = Instance.new('Part')
part.Touched:connect(function() print(part) end)
end
The above part will stick around in memory forever even though there is no way to access it, since the connected function has a reference to the part. That’s why actually Destroy’ing things is important vs just throwing them into nil, because Destroy will disconnect those connections that may leak references otherwise.
There are actually some VERY rare cases in which the scripts do get gc’d, but I’ve only been able to have this happen with one or two methods which really limit what it can do.
Are you sure? IIRC Roblox does garbage collect objects if there’s no Lua thread holding a reference to it and the DataModel doesn’t have a hold on it. If there’s a script holding the connection in memory then it won’t be garbage collected, but in your case you aren’t keeping that connection in any scope.
EDIT: I see what you mean, but in this scenario it seems like it should be weakly connected, given the context of the signal. If the object has no way of being changed because it has been isolated from any strong references to the object, then it should be garbage collected? If it isn’t doing this, then it’s probably a bug that could be fixed.
Something which should be clarified:
This method of theft prevention only applies on the Server, and does not apply to the Client as you have no control over the physical Client itself. Sorry to burst bubbles, I just wanted to ensure no one tried this expecting to protect local source.
Afaik all Roblox connections are created equal. That seems like it should gc, but realize there still is an upvalue reference to it, which was CLOSE’d. It’s a bit ambiguous as to what it may actually do.