• 🏆 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!

Things That Leak

Level 26
Joined
Aug 18, 2009
Messages
4,097
In your snippet it looks like you are using a global variable. They also create a reference and must be reset to undo it. But unlike local variables, global ones never fall out of scope while the map is being played and can therefore be used anew. So the next time you run that code, it will be overwritten. Global variables in wc3 are also static, you do not allocate them ingame, so your possibility of leaking is fairly limited.

Dynamic global variables would be like entries in a hashtable for example. There you are able to always consume new keys and exhaust the memory continuously. Does FlushChildHashtable/FlushParentHashtable properly clean up the references therein btw?
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
the thing is, globals will decrease ref count n variables they point to when you reassign them(set udg_a = A, set udg_a = B will decrement ref counter of A), but the problem is that locals fall out of scope, and the game for some reason never decrements the ref count for the last object stored inside the local variable, so we have to null variables ourselves.

This is however my understanding from the experiments(assigning endlessly to globals did not increase ram usage for me when I tested it).

No idea about Flushes in hashtable
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
mostly yes.

Basically this:

JASS:
function a takes nothing returns AgentType
    local AgentType h = ...
    //some stuff
    return h
endfunction

//to invoke:
AgentType myType = a()

will leak one refcounter object(4 bytes) per function call.

However, the way to prevent is like this:

JASS:
function a takes nothing returns AgentType
    local AgentType h = ...
    //some stuff
    set GlobalVariableOfSameType = h
    set h = null

    return GlobalVariableOfSomeType
endfunction

//to invoke:
set myLocalVar = a()

This is like 2 additional lines and 1 additional global variable for nothing basically
 

sentrywiz

S

sentrywiz

I want to add my dumb example to things that leak, but its not due to a trigger. Therefor I'm not sure it belongs in this thread, but it belongs somewhere.

If you're gonna use Shockwave, never set its missile speed and terrain deformations to 0.
Its gonna create a massive lag, and then crash after a while.

Always use channel for triggered spells.
 
Level 4
Joined
Jun 30, 2014
Messages
72
Stupid Question?

note that I have no real knowledge of scripting. I have copied some Custom Scripts and used them, but don't really understand the "inner workings" of it so to speak.
If I create a Sound or a Special Effect, then destroy it later, do I need to destroy the location?
Like so:
  • LegionCHECK
    • Events
    • Conditions
    • Actions
      • Special Effect - Create a special effect attached to the overhead of Legion_Check using Abilities\Spells\Items\AIsp\SpeedTarget.mdl
      • Set Legion_Sign = (Last created special effect)
      • Set Legion_Holder = Legion_Check
      • Set Legion_Check = No unit
      • Trigger - Turn on Legion RECOV <gen>
      • Trigger - Turn off (This trigger)
Second trigger:
  • Legion REMOVE
    • Events
      • Unit - A unit Loses an item
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Triggering unit) is A Hero) Equal to True
          • Or - Any (Conditions) are true
            • Conditions
              • (Item-type of (Item being manipulated)) Equal to Legion Mail
              • (Item-type of (Item being manipulated)) Equal to Legion Sword
              • (Item-type of (Item being manipulated)) Equal to Legion Cloak
        • Then - Actions
          • Special Effect - Destroy Legion_Sign
          • Set Legion_Holder = No unit
          • Trigger - Turn off Legion RECOV <gen>
          • Trigger - Turn on Legion <gen>
          • Trigger - Turn on LegionCHECK <gen>
        • Else - Actions
          • Do nothing
Should I add "Remove Location" Custom Scripts?
 
Level 4
Joined
Jun 30, 2014
Messages
72
Duh. I feel like a... Peon.

I should have figured that out myself. Units are "things" (so are destructibles) and not "places".
By the way, do regions pre-placed on the map leak?
(ex: from my current map, a region "Floorpad 1", it makes a door doodad open)
I don't see why they should, regions aren't points.
Also, should I RemoveLocation for triggers that use the center of a pre-placed region?
Like "Unit - Create 1 Footman for Player 1 (Red) at (Center of SpawnFootman)"
 
Level 4
Joined
Jun 30, 2014
Messages
72
Thanks.

Thank you, made things more clear.
If I have a point array, how do I call Remove Location for each index?
Or do I just put the variable name into the script and ignore the index numbers and it will do all locations for that point array?

The point array is like this:
  • Set LeapTemps[(Integer A)] = (LeapTarget offset by LeapStep[(Integer A)] towards LeapMoveAngle degrees)
I have 10 or so temp locations per each cast of the spell this is for, so removing all of them is important.
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
quick question,
if you use a variable multiple times before clearing it, does it leak?

A leak is a variable stored in the memory which you can no longer access. How many times you use something has no baring whether it leaks or not.

for example local unit u = GetTriggerUnit(), we have now created a variable containing a unit, but once the function is done this data is still stored but not retrievable.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
not true entirely.

Variables are only pointers, they dont store anything physically, they just point to your memory, + GetTriggerUnit does not allocate any memory, so all you really leak is handleid if you dont null u.

Light, yes:
JASS:
local location l = Location(0, 0)
set l = Location(0, 1)
call RemoveLocation(l)
set l = null

will leak 1 location, because the second call to location makes l point to somewhere else, but the memory itself is still in there(allocated), so it cant be freed = memory leak
 
Level 7
Joined
Mar 10, 2013
Messages
366
Isn't it possible to create like a "Garbage Collector" to Destroy leaked Locations?

It really sounds totally odd that a position that wans't even stored in a variable to leak (I know it actually uses it code-behind, but just looks retarded to me that Blizzard didn't did that).
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,232
Isn't it possible to create like a "Garbage Collector" to Destroy leaked Locations?

It really sounds totally odd that a position that wans't even stored in a variable to leak (I know it actually uses it code-behind, but just looks retarded to me that Blizzard didn't did that).
They did this for StarCraft II. Seeing how WC3 even has a handle table with reference count, either it lacking was an oversight or it does exist but does not work.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,232
Is it possible to create a custom one, then?
Yes one could use wrapper functions to create such a system. However these will come at a heavy performance cost. It is far easier/efficient to use the destructor functions when appropriate.

A third party optimizing JASS re-compiler might be able to detect some leaks and automatically resolve some types of them. However it should always generate a warning and even throw an error if it is certain there is a leak that cannot be resolved.

For Blizzard I would not imagine it being that hard, possibly for one person a day of work or two depending on the code complexity as well as giving basic testing. Maybe more work needed to fix some oversights down the line. It would deprecate the destructor natives.
 
Level 7
Joined
Mar 10, 2013
Messages
366
Yes one could use wrapper functions to create such a system. However these will come at a heavy performance cost. It is far easier/efficient to use the destructor functions when appropriate.

A third party optimizing JASS re-compiler might be able to detect some leaks and automatically resolve some types of them. However it should always generate a warning and even throw an error if it is certain there is a leak that cannot be resolved.

For Blizzard I would not imagine it being that hard, possibly for one person a day of work or two depending on the code complexity as well as giving basic testing. Maybe more work needed to fix some oversights down the line. It would deprecate the destructor natives.
No, I mean like a real Garbage collector, that from time to time, clears up memory space.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,232
No, I mean like a real Garbage collector, that from time to time, clears up memory space.
I doubt memory fragmentation is much of a problem in WC3. For all we know WC3 might already periodically perform a garbage collection cycle, if its allocation structure permits.

People would find it much more useful to have leak prone objects auto destruct.
 
Level 15
Joined
Mar 25, 2016
Messages
1,327
Are you sure @TriggerHappy ? In both functions local force f = CreateForce() is used.
I thought you have to destroy the forces, so they don't leak.
I rarely use forces, so please correct me, if I am wrong.
JASS:
function GetPlayersByMapControl takes mapcontrol whichControl returns force
    local force f = CreateForce()
    local integer playerIndex
    local player  indexPlayer

    set playerIndex = 0
    loop
        set indexPlayer = Player(playerIndex)
        if GetPlayerController(indexPlayer) == whichControl then
            call ForceAddPlayer(f, indexPlayer)
        endif

        set playerIndex = playerIndex + 1
        exitwhen playerIndex == bj_MAX_PLAYER_SLOTS
    endloop

    return f
endfunction

JASS:
function GetPlayersMatching takes boolexpr filter returns force
    local force f = CreateForce()
    call ForceEnumPlayers(f, filter)
    call DestroyBoolExpr(filter)
    return f
endfunction
 
Level 9
Joined
May 31, 2004
Messages
90
how it feels when i try to fix the leaks in my map right now while i am reading through this .

0e55f12aae81659083c7f2e17674d66d.jpg



Did the guys from Blizzard back then not think about it or did they not care because they thought it doesnt matter?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,232
Did the guys from Blizzard back then not think about it or did they not care because they thought it doesnt matter?
JASS2 was never intended to be used in the ways people have ended up using it. One can safely assume the "local declared local handle variable reference counter leak on return bug" was an oversight/programming error.
 
Level 9
Joined
May 31, 2004
Messages
90
JASS2 was never intended to be used in the ways people have ended up using it. One can safely assume the "local declared local handle variable reference counter leak on return bug" was an oversight/programming error.

yeah, i guess they did not expect people to create such complex maps or games with it, for normal melee maps it realy doesnt matter at all.
 
Guess what, the ones who made campaing maps (the only guys who ever worked with JASS2, obviously) had no idea about programming. They are game designers. They had no idea about inneries at all. So nobody ever fixed those issues. What u should think, is rather "why the fuck they didn't fixed it with later patches", which will reveal ugly truth for you.


The fact we even GET updates to this 16 year old game is mind blowing. Figuring out how to work with this old engine is what keeps it an ever-ongoing pleasure/struggle.
 
Guess what, the ones who made campaing maps (the only guys who ever worked with JASS2, obviously) had no idea about programming. They are game designers. They had no idea about inneries at all. So nobody ever fixed those issues. What u should think, is rather "why the fuck they didn't fixed it with later patches", which will reveal ugly truth for you.

Welcome back!
 
????? Titan Quest. Game with much lower hype was updated and HEAVILY. Stop this retarded "16 yo" bullshit, it have nothing to do with the facts they did nothing yet, except for breaking tons of stuff for past 1.5 years.
Lol, the support for this game is better than what they've done with Hearthstone. Calm down kiddo.
 
>>halved official servers online
>>support
w/e
Considering how much money they extort from their HS players and how anything they invest into WarCraft 3 is a literal charity, yes, the support for WarCraft 3 is much better than HS. Do they have more manpower on maintaining HS? Naturally. It keeps the cash cow alive. But they don't care about existing cards: just print more. The inflation (aka Power Creep) has killed the game, which was an intentional design choice to run players into the ground who don't pour money into the game.

Meanwhile, I spent 40 bucks on WarCraft 3 16 years ago, another 30 15 years ago, and I've never had to pay another dime since. The fact they choose to maintain this game instead of dump it is literally a VERY GOOD THING.
 
Level 11
Joined
Jun 2, 2004
Messages
849
Ain't the user's fault if the program does its job poorly. There's a reason every scripting language and most high level languages have garbage collection; it's not something the programmer really ought to worry about.

Wc3's excuse is being a really old game. Even considering that, it's still a bit poorly coded (see the laughable way the implemented localizations). I don't blame new coders at all for having leaks; it's an arcane and unintuitive process to remove them, easy though it may be once you know how.
 
Level 4
Joined
Jul 10, 2013
Messages
73
  • Leak
    • Events
    • Conditions
    • Actions
      • Unit - Move (Triggering unit) instantly to ((Position of (Triggering unit)) offset by 100.00 towards 180.00 degrees)
      • -------- Leaks Twice! --------
      • -------- --------
      • Set TempPoint = (Position of (Triggering unit))
      • Unit - Move (Triggering unit) instantly to (TempPoint offset by 100.00 towards 180.00 degrees)
      • Custom script: call RemoveLocation(udg_TempPoint)
      • -------- Still leaks a location --------
      • -------- --------
      • Set TempPoint = (Position of (Triggering unit))
      • Set TempPoint2 = (TempPoint offset by 100.00 towards 180.00 degrees)
      • Unit - Move (Triggering unit) instantly to TempPoint2
      • Custom script: call RemoveLocation(udg_TempPoint)
      • Custom script: call RemoveLocation(udg_TempPoint2)
      • -------- Finnaly no leaks! --------
PolarProjection(Point with polar offset) also creates a location, meaning that it has to be set to a variable and removed.

Does this include something when you create it with default building facing, meaning you only have to worry about this if it is not in default?
  • Set Point = (Random point in Hives <gen>)
  • Unit - Create 1 Hive (H) for Player 12 (Brown) at Point facing Default building facing degrees
  • Custom script: call RemoveLocation(udg_Point)
 
Top