• 🏆 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] Leaks

Status
Not open for further replies.
Level 20
Joined
Apr 22, 2007
Messages
1,960
Earth-Fury said:
(There are some bugs in this. I think its unit states, I forget.)
Yes, for the IsUnitType native. The thing is, booleans are meant to be either 0 (false) or 1 (true). IsUnitType, on the other hand, sometimes returns boolean values labeled 64 or things like that. The thing with Jass is it evaluates comparisons in a weird way.

JASS:
return IsUnitIllusion(someUnit)
// The line above will evaluate the returned value of IsUnitIllusion.
//If the value is anything other than 1 (true), the function will return false.

return IsUnitIllusion(someUnit)==true
// The line above will evaluate the returned value of IsUnitIllusion.
// Then a boolean comparison will be made with the returned value
// and the true value. In this case, the function will return true if 
// IsUnitIllusion(someUnit) returns anything except 0 (false).

return IsUnitType(someUnit, SOME_BUGGY_UNIT_TYPE_CONSTANT)
// The problem with the above line is sometimes, IsUnitType returns
// true values which are not 1, but 64 or something like that. That
// means that, without the ==true, these boolean comparisons will
// ineffectively return false.
 
Level 19
Joined
Sep 4, 2007
Messages
2,826
May I null my integer variable?
  • Set RandomValue = (Random integer number between 6 and 10)
  • Set SelectChosenUnits = (Random RandomValue units from SelectAllUnits)
  • Custom script: set udg_RandomValue = null
Earth-Fury, those variables only update every 600 seconds and there is like 50% of that trigger being executed.
 
Level 20
Joined
Apr 22, 2007
Messages
1,960
Well, the variables you don't need to null are:
JASS:
integer
real
code
boolean
string
// The ones above are Wc3 native types. They do not have to be nulled
// Only handles have to be nulled, then again, not ALL handle extensions.
// All of the other types whose functions return constant values:
player // is a handle.
boolexpr // is a handle.
race // is a handle...
// etc...
 
Level 12
Joined
Aug 20, 2007
Messages
866
Erm

Ok, variables contain a small amount of information (i think 8 bytes or so), and things like reals, integers, booleans, etc. are numbers that represent something in binary directly

While, handles are large pieces of information, and the variables simply point to them

When you null a variable, it simply clears the 8 bytes of information in them, but the "destroy" functions eliminate the whole handle (not the variable though!)

So, wouldn't you want to null the player variable, because it is pointing to the player handle, and would leave that tiny little variable leak??? (if let's say it was a local)
 
Level 11
Joined
Feb 18, 2004
Messages
394
Ok, variables contain a small amount of information (i think 8 bytes or so), and things like reals, integers, booleans, etc. are numbers that represent something in binary directly

While, handles are large pieces of information, and the variables simply point to them

When you null a variable, it simply clears the 8 bytes of information in them, but the "destroy" functions eliminate the whole handle (not the variable though!)

So, wouldn't you want to null the player variable, because it is pointing to the player handle, and would leave that tiny little variable leak??? (if let's say it was a local)

Correct up untill the last paragraph. The variables don't leak. They are properly allocated and deallocated by the VM. What does cause issue, and the reason we null handles, is the broken reference counter.

set SomeUnit = CreateUnit()

That creates a new unit. It also assigns a variable to it. The act of assigning a variable to it increases the reference count on the internal handle object.

set SomeAlsoUnit = SomeUnit

That again increases the reference counter, as you now have two variables pointing at the unit: SomeUnit and SomeAlsoUnit.

The problem occurs when a function returns. Lets say you have a function such as this:
JASS:
function Abc takes nothing returns nothing
    local unit u = CreateUnit(...)
endfunction
Every time you call that function (call Abc()) you create a new unit, which is just fine. However, you also increase the reference count for the unit. Because of a bug, the reference count is not automatically decreased for the created unit once the function is done. The pointer also ceases to exist once the function is done, as the variable that held it no longer exists! (Or rather, the instance of that variable that held the actual pointer no longer exists.)

So, the solution to the problem is to null the variables before the function returns:
JASS:
function Abc takes nothing returns nothing
    local unit u = CreateUnit(...)
    set u = null
endfunction
by setting u to null, we get rid of the pointer that pointed at the created unit. The set statement works properly in that it will decrease the reference counter.

Now, as for why reference counts actually matter: (Warning: Not everything to follow will be 100% true / accurate. I don't know everything :p)

When you create a new handle-type object like a unit, location, group, etc., it allocates a space on an internal table of handle objects. These handle objects store the reference count as well as some other stuff needed by the internals of the game. When you destroy a handle, and reduce its reference count to 0, it is removed from this table. If you do not reduce its reference count to 0, it still exists in the table of handles, even if the actual data (like a unit, a group, a location) is gone.

This is not a problem for things like players, as the function Player(whateverNumber) will always return a pointer to the same handle for the same input. You also can not destroy players, so it really doesn't matter what the reference count is.

This is a problem for anything that will eventually be destroyed / removed completely from the game.


Sidenote: I blame lack of sleep if this makes no sense.
 
Level 12
Joined
Aug 20, 2007
Messages
866
Ohhhhhhhhh

Uh-oh
I gave a bunch of ppl some advice that isn't exactly correct ><

No, that explanation makes perfect sense
So, warcraft appropriately removes variables, it's the reference count that must be dropped in order for warcraft to fully remove a handle, even if it is destroyed
 
Level 17
Joined
Sep 2, 2005
Messages
1,029
Returning a value is very different from doing something. Returning a value is one of a multitude of purposes a sub or function can do. Functions Normally send a value back to whatever called them. A Sub can do other stuff, but nothing is sent back (because it was made a sub because nothing needed to be sent back.
 
Status
Not open for further replies.
Top