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

Things That Leak

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
default building facing is just a constant: bj_UNIT_FACING = 270.0
There is no difference between using a constant/variable or a value

The trigger you posted does not leak, because you removed the location. Changing the facing of the unit does not create a new location or something like that, so it does no leak.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
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.

memory leaks are not anywhere near as dangerous as data leaks, and no garbage collector can prevent those(speaking of unclosed file handles, unclosed database connections, threads that are alive indefinately because they reference some data that lives longer than them, locked mutexes, and so on)
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
memory leaks are not anywhere near as dangerous as data leaks, and no garbage collector can prevent those(speaking of unclosed file handles, unclosed database connections, threads that are alive indefinately because they reference some data that lives longer than them, locked mutexes, and so on)
Depends entirely on the severity of the memory leak. If you are leaking several megabytes per second it is pretty bad.
 
how dare you? blizz working their asses off for last 1.5 year to allow u to run this game! And dont u dare saying u could run it before, w/o new patches. U couldnt. End of story.

I don't think he's attacking the game itself. What he meant to say was that the coding could have been done better, most particularly garbage collection, which (in my opinion) is non-existent in the game.

When encountering memory in most high-level languages (scripting), you would not need to worry about them at all since there is (should be) a garbage-collecting algorithm that takes care of the memory-cleaning for you. In Warcraft 3, there is no such algorithm, and so we have to deal with cleaning up the leaks ourselves.

U could run it before :p (Just kidding, don't get angry at this)
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
When encountering memory in most high-level languages (scripting), you would not need to worry about them at all since there is (should be) a garbage-collecting algorithm that takes care of the memory-cleaning for you. In Warcraft 3, there is no such algorithm, and so we have to deal with cleaning up the leaks ourselves.
Which is why they added one for Galaxy in StarCraft II...
 
Level 9
Joined
May 31, 2004
Messages
90
Can someone please explain to me why this trigger has 7 location leaks (i testet with Jass Checker,
i used the scrip to remove the Location variables every time? (ChaosFallPoint & ChaosFallEffectPosition)

  • Aktionen
    • Einheit - Kill ChaosFallUnit
    • Set ChaosFallPoint = (Target point of ability being cast)
    • Einheit - Create 1 ChaosBomb for (Owner of Chaos Lord 0027 <gen>) at ChaosFallPoint facing 0.00 degrees
    • Custom script: call RemoveLocation(udg_ChaosFallPoint)
    • Set ChaosFallUnit = (Last created unit)
    • Animation - Change ChaosFallUnit flying height to 50.00 at 200.00
    • Einheit - Set level of ChaosBombDummy for ChaosFallUnit to (Level of ChaosFall for Chaos Lord 0027 <gen>)
    • Wait 0.20 seconds
    • Animation - Change ChaosFallUnit flying height to 50.00 at 600.00
    • Wait 0.20 seconds
    • Animation - Change ChaosFallUnit flying height to 50.00 at 800.00
    • Wait 0.20 seconds
    • Animation - Change ChaosFallUnit flying height to 50.00 at 1000.00
    • Wait 0.20 seconds
    • Animation - Change ChaosFallUnit flying height to 50.00 at 1200.00
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • 'IF'-Bedingungen
        • (ChaosFallUnit is alive) Gleich True
      • 'THEN'-Aktionen
        • Do nothing
      • 'ELSE'-Aktionen
        • Skip remaining actions
    • Einheit - Order ChaosFallUnit to Menschen-Bergkönig - 'Donnerschlag'
    • Set ChaosFallEffectPosition = (Position of ChaosFallUnit)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Objects\Spawnmodels\Other\NeutralBuildingExplosion\NeutralBuildingExplosion.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Wait 0.02 seconds
    • Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 0.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Wait 0.02 seconds
    • Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 60.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Wait 0.02 seconds
    • Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 120.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Wait 0.02 seconds
    • Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 180.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Wait 0.02 seconds
    • Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 240.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Wait 0.02 seconds
    • Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 300.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Einheit - Kill ChaosFallUnit
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 0.00 degrees)
A location leak.
Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 60.00 degrees)
Another location leak.
Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 120.00 degrees)
Location leak 3 and 4.
Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 180.00 degrees)
Location leak 5.
Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 240.00 degrees)
Leak 6.
Set ChaosFallEffectPosition = ((Position of ChaosFallUnit) offset by 200.00 towards 300.00 degrees)
Leak 7.

There are 6 leaks (1, 2, 3, 5, 6 and 7) caused by creating a location using "(Position of ChaosFallUnit)" and not removing it. The last leak, leak 4, is the result of not removing the value of ChaosFallEffectPosition before reassigning it.
 
Level 9
Joined
May 31, 2004
Messages
90
i dont undestand, does this not remove the location?

Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)

oh well , it is 6 leak, i forgot one there.

but still, does it not work with polar offset?
 
Last edited:
Level 23
Joined
Apr 16, 2012
Messages
4,041
the problem is that (Position of ChaosFallUnit) creates new location every time it is used, then it shoves that location into another piece of code which will do the polar projection you requested(the offset + angle) and then return the second location to you, the first one is forever in the memory
 
Level 9
Joined
May 31, 2004
Messages
90
the problem is that (Position of ChaosFallUnit) creates new location every time it is used, then it shoves that location into another piece of code which will do the polar projection you requested(the offset + angle) and then return the second location to you, the first one is forever in the memory

hmm i think i understand it now and looks like i was able to fix it with a second Point, now the JassChecker does not show the trigger anymore, this is mindbugging.

  • Aktionen
    • Einheit - Kill ChaosFallUnit
    • Set ChaosFallPoint = (Target point of ability being cast)
    • Einheit - Create 1 ChaosBomb for (Owner of Chaos Lord 0027 <gen>) at ChaosFallPoint facing 0.00 degrees
    • Custom script: call RemoveLocation(udg_ChaosFallPoint)
    • Set ChaosFallUnit = (Last created unit)
    • Animation - Change ChaosFallUnit flying height to 50.00 at 200.00
    • Einheit - Set level of ChaosBombDummy for ChaosFallUnit to (Level of ChaosFall for Chaos Lord 0027 <gen>)
    • Wait 0.20 seconds
    • Animation - Change ChaosFallUnit flying height to 50.00 at 600.00
    • Wait 0.20 seconds
    • Animation - Change ChaosFallUnit flying height to 50.00 at 800.00
    • Wait 0.20 seconds
    • Animation - Change ChaosFallUnit flying height to 50.00 at 1000.00
    • Wait 0.20 seconds
    • Animation - Change ChaosFallUnit flying height to 50.00 at 1200.00
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • 'IF'-Bedingungen
        • (ChaosFallUnit is alive) Gleich True
      • 'THEN'-Aktionen
        • Do nothing
      • 'ELSE'-Aktionen
        • Skip remaining actions
    • Einheit - Order ChaosFallUnit to Menschen-Bergkönig - 'Donnerschlag'
    • Set ChaosFallEffectPosition = (Position of ChaosFallUnit)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Objects\Spawnmodels\Other\NeutralBuildingExplosion\NeutralBuildingExplosion.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Wait 0.02 seconds
    • Set ChaosFallPoint = (Position of ChaosFallUnit)
    • Set ChaosFallEffectPosition = (ChaosFallPoint offset by 200.00 towards 0.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Custom script: call RemoveLocation(udg_ChaosFallPoint)
    • Wait 0.02 seconds
    • Set ChaosFallPoint = (Position of ChaosFallUnit)
    • Set ChaosFallEffectPosition = (ChaosFallPoint offset by 200.00 towards 60.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Custom script: call RemoveLocation(udg_ChaosFallPoint)
    • Wait 0.02 seconds
    • Set ChaosFallPoint = (Position of ChaosFallUnit)
    • Set ChaosFallEffectPosition = (ChaosFallPoint offset by 200.00 towards 120.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Custom script: call RemoveLocation(udg_ChaosFallPoint)
    • Wait 0.02 seconds
    • Set ChaosFallPoint = (Position of ChaosFallUnit)
    • Set ChaosFallEffectPosition = (ChaosFallPoint offset by 200.00 towards 180.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Custom script: call RemoveLocation(udg_ChaosFallPoint)
    • Wait 0.02 seconds
    • Set ChaosFallPoint = (Position of ChaosFallUnit)
    • Set ChaosFallEffectPosition = (ChaosFallPoint offset by 200.00 towards 240.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Custom script: call RemoveLocation(udg_ChaosFallPoint)
    • Wait 0.02 seconds
    • Set ChaosFallPoint = (Position of ChaosFallUnit)
    • Set ChaosFallEffectPosition = (ChaosFallPoint offset by 200.00 towards 300.00 degrees)
    • Spezialeffekt - Create a special effect at ChaosFallEffectPosition using Abilities\Spells\Undead\Possession\PossessionMissile.mdl
    • Spezialeffekt - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ChaosFallEffectPosition)
    • Custom script: call RemoveLocation(udg_ChaosFallPoint)
    • Einheit - Kill ChaosFallUnit
 
Level 8
Joined
Jul 10, 2008
Messages
353
TriggerRemoveCondition
TriggerRemoveAction

Are those 2 really needed before DestroyTrigger to remove leaks. Do actions and conditions of triggers really leak?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
my map still leaks, is it because of the number of units?
How do you know it is leaking?
Are those 2 really needed before DestroyTrigger to remove leaks. Do actions and conditions of triggers really leak?
Only triggeraction leak as far as I can tell. If one does not destroy the triggeraction then there is a handle ID leak.

If one just destroys a trigger with triggercondition bound to it then all handles get recycled.
 
Level 18
Joined
Jan 12, 2011
Messages
1,512
in my map, undead units come from a base and attack an orc base, at the first few waves it's not leaking, but after some time like 100 seconds, the units wait some time and then they walk, wait again ,walk.
could someone show me the entire list of leaks?

That's because too many units are in the map at the same time, the game itself is made for a single core so it takes longer for it to compute where the unit should walk, it isn't a leak.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
in my map, undead units come from a base and attack an orc base, at the first few waves it's not leaking, but after some time like 100 seconds, the units wait some time and then they walk, wait again ,walk.
could someone show me the entire list of leaks?
No leak there. Just you are hitting the WC3 engine movement update limit.

Warcraft III issues 1 micro move update per player per game frame (every 0.03 seconds?).
but how on bigger maps like coming of the horde it dont happen?
Could be a number of factors. The units could be spread across more players so get more micro move updates per unit time. The units could also have smaller collision so the micro move updates last longer as movement stops upon non-air unit on unit collision. It is also possible the terrain pathing is simpler so micro move updates are issued for longer distances.

It is also simply possible you created too many/big regions and so broke the game engine. For example on a 480*480 map a few dozen "unit enters playable map area" events will totally break unit path finding to the point they start mindlessly walking into walls like an RTS from 1990.
 
Level 20
Joined
Jul 12, 2010
Messages
1,717
guys quick question:
does playable map area & entire map leak a location?
  • Animation - Play the stand animation for all doodads of type Fire within (Playable map area)
  • Animation - Play the stand animation for all doodads of type Fire within (Playable map area)
or does this trigger leak in general? since it picks all type of a doodad?

also I remember a guy saying to me that bj leaks
  • Custom script: set bj_wantDestroyGroup = true
so does this leak or no? (I don't have time to scroll through 62 pages lol)
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
(Playable map area) just returns a bj variable that is set once at map init, no

(Entire map) is a native call creating a new rect

set bj_wantDestroyGroup = true is for various group-targeted GUI calls like Pick Every Unit In Group And Do Action. It destroys the group afterwards and may be useful if you created a new group priorly like with (Units In Range) functions and such.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
(Playable map area) just returns a bj variable that is set once at map init, no

(Entire map) is a native call creating a new rect

set bj_wantDestroyGroup = true is for various group-targeted GUI calls like Pick Every Unit In Group And Do Action. It destroys the group afterwards and may be useful if you created a new group priorly like with (Units In Range) functions and such.
The (Entire map) leaks without removing the rect, but (Playable map area) is just a reference.

Every 'pick all units' call imcreases permanently a local handle reference indicator. against said group. That's why Spell System uses group recycling - so the system never leaks unit group handles when GUI users do the Pick All Units stuff.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Every 'pick all units' call imcreases permanently a local handle reference indicator. against said group.
No it does not.

The following proves it do not cause a reference counter leak.
JASS:
function Trig_For_Group_Leak_Test_Func001A takes nothing returns nothing
    call SetUnitAnimation(GetEnumUnit(), "death")
endfunction
function Trig_For_Group_Leak_Test_Actions takes nothing returns nothing
    local group g = CreateGroup()
    call BJDebugMsg(I2S(GetHandleId(g)))
    call GroupEnumUnitsInRect(g, GetPlayableMapRect(), null)
    set bj_wantDestroyGroup = true
    call ForGroupBJ(g, function Trig_For_Group_Leak_Test_Func001A )
    set g = null
endfunction
//===========================================================================
function InitTrig_For_Group_Leak_Test takes nothing returns nothing
    set gg_trg_For_Group_Leak_Test = CreateTrigger(  )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_For_Group_Leak_Test, Player(0) )
    call TriggerAddAction( gg_trg_For_Group_Leak_Test, function Trig_For_Group_Leak_Test_Actions )
endfunction

Pressing ESC any number of times will cycle through the same HandleIDs for the group. Meaning no handle reference counter leak.

What does leak a handle reference counter is this common GUI group function.
JASS:
function GetUnitsInRectAll takes rect r returns group
    return GetUnitsInRectMatching(r, null)
endfunction
Because the following leaks a handle reference count.
JASS:
function GetUnitsInRectMatching takes rect r,boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRect(g, r, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Garbage collection also has its disadvantages: Garbage collection (computer science) - Wikipedia
Some objects like sounds and special effects are even useful after you lost their reference. Fog modifiers never become useless.
You will get leaks that are intended, so the garbage system must not simply clear all leaks, but also take into consideration, which objects still have an effect.
You would need a very complicated garbage collection algorithm, that would probably impact performance.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Location leaks do not exist in jass for example.

What do you mean? You can create locations in jass and have to clean them up. Location variables are ref-counted handles, too.

Garbage collection also has its disadvantages: Garbage collection (computer science) - Wikipedia
Some objects like sounds and special effects are even useful after you lost their reference. Fog modifiers never become useless.
You will get leaks that are intended, so the garbage system must not simply clear all leaks, but also take into consideration, which objects still have an effect.
You would need a very complicated garbage collection algorithm, that would probably impact performance.

The jass engine is not the same as internal mechanics. Sounds and special effects have their own life cycle anyway, erasing their references is only relevant for the jass handles and manually doing it does not cause havoc, either. Not automatically nullifying local variables/removing refs on the end of the function is a mere blunder on Blizzard's part that can be fixed by a precompiler with minimal overhead (exception: local arrays).
 
Level 12
Joined
Mar 24, 2011
Messages
1,082
@Abishkar
  • Events
    • Time - Every 1.0 sek of game time
  • Conditions
  • Actions
    • Set TempPoint = Center of region <gg_Sapwn_Region_0001>
    • Unit - Create 1 footman at TempPoint for player 1(red) facing 0.00 degree
    • Custom script: call RemoveLocation(udg_TempPoint)
    • Set TempPoint = Centre of region <gg_Attack_Here_Region_0002>
    • Unit - Order (Last Created Unit) to Attack-Move TempPoint
    • Custom script: call RemoveLocation(udg_TempPoint)
Like this?
Have in mind, I just typed this in the web browser.
Syntax may not accurately reflect WE equivalents ;)

Note that "TempPoint" and "udg_TempPoint" are exactly the same thing.
First one would be it's name in GUI and the second would be for JASS.
udg = User Defined Global, those are the variables that you create with the variable editor.

//Edit: If you require any further help, I'd suggest opening your own thread around

regards
-Ned
 
Last edited:
Level 7
Joined
Dec 17, 2017
Messages
134
Holy damn, do I have to call after each? Then it will be such a pain in the ass.
I mean like this, a footman is spawned from Region A and ordered to move to Region B. Then, a knight is spawned from the same Region A and ordered to move to Region B. So, will I call after The footman spawn and again call after the Knight spawn? Or do I have to call after all the units have spawned? @nedio95
P. S. : Love how you write "Regards - Ned" in the end of every message. Ha ha :)
 
Level 12
Joined
Mar 24, 2011
Messages
1,082
Holy damn, do I have to call after each? Then it will be such a pain in the ass.
I mean like this, a footman is spawned from Region A and ordered to move to Region B. Then, a knight is spawned from the same Region A and ordered to move to Region B. So, will I call after The footman spawn and again call after the Knight spawn? Or do I have to call after all the units have spawned? @nedio95
P. S. : Love how you write "Regards - Ned" in the end of every message. Ha ha :)
Every time you need to use a point.

If you are going to re-use a point you could not de-allocate it.
E.g.
  • Events
    • Map initialization
  • Conditions
  • Actions
    • Set SpawnPoint[0] = Centre of SpawnRegion1
    • Set SpawnPoint[1] = Centre of SpawnRegion2
    • Set AttackPoint[0] = Centre of AttackRegion1
    • Set AttackPoint[1] = Centre of AttackRegion2
  • Events
    • Time - Every 1.0 sek of game time
  • Conditions
  • Actions
    • For Loop integer temp_Index from 0 to 1
      • Loop
        • Unit - Create 1 footman at SpawnPoint[temp_Index] for player 1(red) facing 0.00 degree
        • Unit - Order (Last Created Unit) to Attack-Move AttackPoint[1]
If your regions are not used for anything else, this may be a better approach.

PS: regards
-Ned
 
Top