• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

JASS local variables

Status
Not open for further replies.
Level 12
Joined
May 22, 2015
Messages
1,051
I have some questions about JASS local variables. I know I need to set Handle objects to null. I guess this lets the game know they are no longer being used so the memory for the pointer is freed. Do I also need to set integers / reals to 0, strings to empty string, etc?

Also let's say I have a trigger like this:
JASS:
function test takes nothing returns nothing
    local unit u

    if (false) then
        set u = GetTriggerUnit()

        // Do stuff

        set u = null
    endif
endfunction
Will this leak? Do I need to put "set u = null" outside the if statement or is it fine like that?

How does it work if I do:
JASS:
function test takes nothing returns unit
    local u = GetTriggerUnit()
    return u
endfunction
Would that leak? How would I deal with it otherwise? Would I need to use a global and use that elsewhere? - basically removing the return in place of using the global.

Thanks in advance.
 
Level 12
Joined
Feb 22, 2010
Messages
1,115
You never need to null integer, real, boolean, string, code type variables.

Edit:no

In your second example you either need to use a global, or do your work without returning a local variable.
 
Level 12
Joined
Feb 22, 2010
Messages
1,115
IcemanBo is right about first example, I didn't see variable u was never assigned.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
First, lets talk about this leak, so people understand better.

You dont leak the unit or anything like that, you leak the handleid, which is believed to be 4 byte structure(it is a reference counter, only present for agents, not for all handles)(http://jass.sourceforge.net/doc/api/common_j-source.shtml to see which is and which isnt agent).

The problem here is, that when you set any variable into any agent, its reference counter is increased(integer) and the unit can really be recycled(the handleId reassigned to something else) after the reference counter hits 0.

The problem here, as I see it personally is that when you set global variable into something, then the reference counter of the object that was stored inside the variable before will get its reference counter decreased, and the same goes for locals. The real problem is that when locals fall out of scope(function returns/execution falls out of scope), the local variables dont decrease reference counter(does not happen to arguments oddly enough, which are also local variables effectivelly) and so we have to do it manually, by setting the agents to appropriate values(null, because null doesnt care about ref counting).

So no, in the first one you dont need the set to null outside, because if the if block does not execute, the unit is not set to anything.

The second one is a bit tricky, you will leak, but I will just say, that you should code according to this rule: logicality over obscurity.

Basically, it is nice that you leak, but you or the users of your script(another coders in this regard) may bash their head against a wall a few times after they see function like "GetSomethingSomething", which will not return anything, but will set some global variable into something.

Code logically so that you make sense, if you have to return unit, return unit, if you dont have to return unit, you can return it anyways :D

Possible fix for the second example, if you want to be tryhard:
you make the function and document it so that you say that global variable with name XXX will be set to value you indended to return.
 
Level 12
Joined
May 22, 2015
Messages
1,051
Thanks for the help, guys!

A workaround for the second problem - could I have a unit parameter that I always set to null? hahaha

Basically it would be like
JASS:
function test takes unit u returns unit
    set u = CreateUnit(...)
    return u
endfunction
and
JASS:
function doStuff takes nothing returns nothing
    local unit u = test(null)
    // do stuff
    set u = null
endfunction
It's a bit obscure, though.

I think I don't need anything like this yet, but it's good to know all this stuff. I have one function that takes a unit and gets another unit, so can I just use the parameter unit as a local variable and return it safely?
 
Level 12
Joined
May 22, 2015
Messages
1,051
Thanks, again, for the help, everyone! The answers were quick and very helpful. This will allow me to clean up some of my code.
 
Level 12
Joined
May 22, 2015
Messages
1,051
Thought of another scenario where I'm not 100% sure what I need to do:
JASS:
function test takes nothing returns nothing
    local group g = CreateGroup()
    local location l = CreateLocation(0, 0) // Don't know the constructor for locations - just pretend this works lol

    // Do stuff

    call DestroyGroup(g)
    call RemoveLocation(l)
    set g = null
    set l = null
endfunction

Do I need to null g, and l there or is that redundant?
 
Status
Not open for further replies.
Top