• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[JASS/AI] Object Leak vs. Reference Leak

Level 19
Joined
Dec 12, 2010
Messages
2,070
That's a guide for mid-level of JASSing, yet even profis don't really understand nulling.

Pretty much everyone knows about jass' thing "a leak". Basically, it's a link to an object you don't need to use anymore. Let's say you had to set location for creeps to go into. You gonna do it like that:
JASS:
local location l = Location(x,y)
if IsLocationVisibleToPlayer(l,GetTriggerPlayer()) then
call IssuePointOrderByIdLoc(GetTriggerUnit(),851297,l)
call RemoveLocation(l)
set l=null
Why do you remove location here? 'Cause you don't need it anymore, you used it once and won't anymore. So you call it's destroyer object RemoveLocation and null the variable.

Let's take different example where you want to register every unit entering specific region
JASS:
function TriggerRegisterEnterRectSimple takes trigger trig, rect r returns event
    local region rectRegion = CreateRegion()
    call RegionAddRect(rectRegion, r)
    return TriggerRegisterEnterRegion(trig, rectRegion, null)
endfunction
That's default Blizzard's function, and even tho it looks leaky, it's not dangerous at all. Created region will be used constantly, it's the thing which has trigger attached to. If you destroy region, trigger will be gone too. You don't need to null it either, since no matter what, region will stay there whole game, and you don't need to utilize it anyhow.

See the difference?

Leak's definition
Common description of leak is either not nulling, either not destroying of an object you won't use anymore. Thing is, nulling isn't big deal at all.

Whenever you assign an object (handle) to variable, it's inner counter increased by 1. Everytime you null object counter reduced by 1. This counter is used only for inner game's functions. It doesn't prevent game from destroying object if user said so - it rather blocks specific handle ID from recycling. Not a big deal, huh?

That means everytime you not null object which is destroyed, you waste 4 bytes of memory. Game won't re-use those, so will take following 4 bytes. So, in order to waste just 1 MB of RAM you have to make 1048576 leaks (1mln+).

Meanwhile object ARE heavy. They have very spreaded stats, like unit could take few KB with all his structures and inner links, while effect takes only few tens of bytes plus very few sub-calls. So, you actually need to remove objects, not the links. Don't starve for nulling everything, better watch out for things you leftover non-destroyed.

You have, let's say, an ability on the hero. On usage you use triggers to handle, and of course you put GetTriggerUnit() into variable for easier access. If you're sure hero won't be removed from the game, you don't need to null him at all. Same goes for destructibles you're not gonna delete, triggers you're not gonna remove, etc etc.

But can it lead to handle overload?
Well, definitely can. In theory. If you're using save games, probably. Because handles are counted with a 4 bytes unsigned counter, which means, at worst case, you may have up to 2^31 entities max, or 2 147 483 647. Seems enough for a few months of gameplay, isnt it?

Also I find HandleID lock very useful for some.. situatoins. This way you don't need to save 0's or nulls in the hashtables, using HandleID, to make sure there's no invalid data. You don't need to clean those either, in fact, but that's definitely not recommended technique.
 
Level 19
Joined
Dec 12, 2010
Messages
2,070
Resource can leak object and it's reference, yes. We usually call it "reference leak" if variables is not nulled, and "object leak" when an object is not destroyed.
I changed my tutorial slightly to match some wordings with handle as reference, but I think my tutorial already covers some important stuff: Memory Leaks
if you actually explain difference between these leaks it's fine
 
Everytime you null object counter reduced by 1
. Game won't re-use those, so will take following 4 bytes. So, in order to waste just 1 MB of RAM you have to make 1048576 leaks (1mln+)
that might be good to note, which I don't atm. Will look for it in some days, where to do best.

Also iirc the id is not even recycled instantly, or? So technicaly it might also work perfectly fine if you null all variables after 10 seconds or so after removal? I'm not very sure how the process works, if it's a periodical lookup or what.
But maybe it's anyways just conufusing in the end and not important.
 
You can null a locals after a triggersleepaction(), or null globals after a timer timeout.

And if a periodic check handles the id recycling each 30 seconds for example, then you might be lucky if you null it only after 10 seconds, I meant.
I just said, I'm not fully aware of how the recylcing process works, but iirc it was not instant (awlays?).
 
Top