• Check out the results of the Techtree Contest #19!
  • Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!

Did nulling unit group cause leak?

Level 11
Joined
Jul 22, 2015
Messages
223
Because i want merge one MUI trigger in one trigger loop with other, i decide to merge it to one variable but the problem (maybe) i'm afraid to it cause leak if i nullified since i don't use it on other trigger , I'm curious if that cause leak or not if i'm nulling one of unit group?

  • Custom script: set udg_AquaKonoGroupDummy[udg_AquaKono[0]] = null
Here for example i merge the trigger

  • Exocirm
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Exorcism
    • Actions
      • Set HeroAbilityLevel = (Level of (Ability being cast) for (Triggering unit))
      • Set HeroAttribute = (Intelligence of (Triggering unit) (Include bonuses))
      • Set HeroLevel = (Hero level of (Triggering unit))
      • Set HeroBaseDamage = (Base Damage of (Triggering unit) for weapon index 1)
      • Set HeroTrait = Magical[(Custom value of (Triggering unit))]
      • Set SongOfPearlBonus = (SongOfPearlDamageMultiplier[SongOfPearlLevel[(Custom value of (Triggering unit))]] x (Max life of (Triggering unit)))
      • Set HeroAllinOne = (((HeroBaseDamage + HeroAttribute) + HeroLevel) + HeroTrait)
      • Set Point[0] = (Position of (Triggering unit))
      • Set AquaKono[0] = (AquaKono[0] + 1)
      • Custom script: set udg_AquaKonoGroupDummy[udg_AquaKono[0]] = CreateGroup()
      • For each (Integer A) from 1 to 5, do (Actions)
        • Loop - Actions
          • Set Point[1] = (Point[0] offset by 400.00 towards (72.00 x (Real((Integer A)))) degrees)
          • Set AquaKonoAngle[AquaKono[0]] = (Angle from Point[1] to Point[0])
          • Unit - Create 1 Aqua Ion Beam for (Owner of (Triggering unit)) at Point[1] facing AquaKonoAngle[AquaKono[0]] degrees
          • Set AquaKonoDummy[AquaKono[0]] = (Last created unit)
          • Unit Group - Add AquaKonoDummy[AquaKono[0]] to AquaKonoGroupDummy[AquaKono[0]]
          • Custom script: call RemoveLocation(udg_Point[1])
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Triggering unit) has buff SongOfPearlBuff) Equal to True
        • Then - Actions
          • Set AquaKonoDamage[AquaKono[0]] = (AquaExorcismB[HeroAbilityLevel] + (SongOfPearlBonus + ((Real(HeroAllinOne)) x AquaExorcismM[HeroAbilityLevel])))
        • Else - Actions
          • Set AquaKonoDamage[AquaKono[0]] = (AquaExorcismB[HeroAbilityLevel] + (0.00 + ((Real(HeroAllinOne)) x AquaExorcismM[HeroAbilityLevel])))
      • Set AquaKonoCaster[AquaKono[0]] = (Triggering unit)
      • Set AquaKonoDelay[AquaKono[0]] = 0.00
      • Set AquaKonoRun[AquaKono[0]] = 0.00
      • Set AquaKonoSpeed[AquaKono[0]] = 15.00
      • Set AquaKonoX[AquaKono[0]] = 0.00
      • Set AquaKonoY[AquaKono[0]] = 0.00
      • Set AquaKonoStage[AquaKono[0]] = 1
      • Set AquaKonoX[AquaKono[0]] = 0.00
      • Set AquaKonoY[AquaKono[0]] = 0.00
      • Set AquaBoolean[AquaKono[0]] = False
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • AquaKono[0] Equal to 1
        • Then - Actions
          • Trigger - Turn on ExocirmLoop <gen>
        • Else - Actions
      • Custom script: call RemoveLocation(udg_Point[0])
  • WaterSplash
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Sacred Water Splash
    • Actions
      • Set HeroAbilityLevel = (Level of (Ability being cast) for (Triggering unit))
      • Set HeroAttribute = (Intelligence of (Triggering unit) (Include bonuses))
      • Set HeroLevel = (Hero level of (Triggering unit))
      • Set HeroBaseDamage = (Base Damage of (Triggering unit) for weapon index 1)
      • Set HeroTrait = Magical[(Custom value of (Triggering unit))]
      • Set SongOfPearlBonus = (SongOfPearlDamageMultiplier[SongOfPearlLevel[(Custom value of (Triggering unit))]] x (Max life of (Triggering unit)))
      • Set HeroAllinOne = (((HeroBaseDamage + HeroAttribute) + HeroLevel) + HeroTrait)
      • Set Point[0] = (Target point of ability being cast)
      • Set AquaKono[0] = (AquaKono[0] + 1)
      • Set AquaKonoX[AquaKono[0]] = (X of Point[0])
      • Set AquaKonoY[AquaKono[0]] = (Y of Point[0])
      • Set AquaKonoCaster[AquaKono[0]] = (Triggering unit)
      • Set AquaKonoDummy[AquaKono[0]] = No unit
      • Set AquaKonoDelay[AquaKono[0]] = 1.98
      • Set AquaKonoRun[AquaKono[0]] = 0.00
      • Set AquaKonoSpeed[AquaKono[0]] = 15.00
      • Set AquaKonoStage[AquaKono[0]] = 2
      • Custom script: set udg_AquaKonoGroupDummy[udg_AquaKono[0]] = null
      • Set AquaBoolean[AquaKono[0]] = False
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Triggering unit) has buff SongOfPearlBuff) Equal to True
        • Then - Actions
          • Set AquaKonoDamage[AquaKono[0]] = (AquaWaterSplash[HeroAbilityLevel] + (SongOfPearlBonus + ((Real(HeroAllinOne)) x AquaWaterSplash2[HeroAbilityLevel])))
        • Else - Actions
          • Set AquaKonoDamage[AquaKono[0]] = (AquaWaterSplash[HeroAbilityLevel] + (0.00 + ((Real(HeroAllinOne)) x AquaWaterSplash2[HeroAbilityLevel])))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • AquaKono[0] Equal to 1
        • Then - Actions
          • Trigger - Turn on ExocirmLoop <gen>
        • Else - Actions
      • Custom script: call RemoveLocation(udg_Point[0])
 
Yes, it does leak.

  • Custom script: set udg_AquaKonoGroupDummy[udg_AquaKono[0]] = CreateGroup()
This creates an object (a unit group) and assigns its handleId to variable/array AquaKonoGroupDummy under index X.
Now handleId stored in AquaKonoGroupDummy[X] references the unit group object. Note that it is not the object itself that is stored in the variable, it is only a reference to the object.

Following action:
  • Custom script: set udg_AquaKonoGroupDummy[udg_AquaKono[0]] = null
just removes the reference. So AquaKonoGroupDummy[X] will no longer refence unit group object.
However there is nothing destroying said object, so it causes memory leak.

  • Custom script: call DestroyGroup(udg_AquaKonoGroupDummy[udg_AquaKono[0]])
will destroy the unit group object referenced by AquaKonoGroupDummy.

---
Also, I do not understand the relationship between Exocirm and WaterSplash triggers. I only see that one is creating unit group while other nulls reference to it.
However what I would like to point is following: If your intention is to create unit group in Exocirm and WaterSplash should destroy that unit group, then what you have currently will not work and it will always leak.
 
Okay, thanks for information, i guess i will revamp my spell because i add too much refernce too merge trigger, because i though it will efficient to track the unit group (because one of trigger didn't actually need unit group, but if i not use that reference it will nasty bug on the spell)

Also, one question are udg_UnitVariable = No Unit cause leak?
Also, I do not understand the relationship between Exocirm and WaterSplash triggers. I only see that one is creating unit group while other nulls reference to it.
However what I would like to point is following: If your intention is to create unit group in Exocirm and WaterSplash should destroy that unit group, then what you have currently will not work and it will always leak.
Because i want to merge it to this loop and destroy it in this loop, i didn't want create too much variable because performance issue.
  • ExocirmLoop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer AquaKono[1]) from 1 to AquaKono[0], do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AquaKonoStage[AquaKono[1]] Equal to 0
            • Then - Actions
              • Set AquaKonoDummy[AquaKono[1]] = AquaKonoDummy[AquaKono[0]]
              • Set AquaKonoCaster[AquaKono[1]] = AquaKonoCaster[AquaKono[0]]
              • Set AquaKonoDelay[AquaKono[1]] = AquaKonoDelay[AquaKono[0]]
              • Set AquaKonoRun[AquaKono[1]] = AquaKonoRun[AquaKono[0]]
              • Set AquaKonoStage[AquaKono[1]] = AquaKonoStage[AquaKono[0]]
              • Set AquaKonoDamage[AquaKono[1]] = AquaKonoDamage[AquaKono[0]]
              • Set AquaKonoGroupDummy[AquaKono[1]] = AquaKonoGroupDummy[AquaKono[0]]
              • Set AquaBoolean[AquaKono[1]] = AquaBoolean[AquaKono[0]]
              • Set AquaKonoChance[AquaKono[1]] = AquaKonoChance[AquaKono[0]]
              • Set AquaKonoX[AquaKono[1]] = AquaKonoX[AquaKono[0]]
              • Set AquaKonoY[AquaKono[1]] = AquaKonoY[AquaKono[0]]
              • Set AquaKono[1] = (AquaKono[1] - 1)
              • Set AquaKono[0] = (AquaKono[0] - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AquaKono[0] Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AquaKonoStage[AquaKono[1]] Equal to 1
                • Then - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • AquaKonoDelay[AquaKono[1]] Greater than or equal to 1.80
                    • Then - Actions
                      • Set Point[2] = (Position of AquaKonoCaster[AquaKono[1]])
                      • Unit Group - Pick every unit in AquaKonoGroupDummy[AquaKono[1]] and do (Actions)
                        • Loop - Actions
                          • Set Point[3] = (Position of (Picked unit))
                          • Set AquaKonoRun[AquaKono[1]] = (Distance between Point[2] and Point[3])
                          • Set AquaKonoAngle[AquaKono[1]] = (Angle from Point[3] to Point[2])
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • AquaKonoRun[AquaKono[1]] Greater than or equal to AquaKonoSpeed[AquaKono[1]]
                            • Then - Actions
                              • Set Point[4] = (Point[3] offset by AquaKonoSpeed[AquaKono[1]] towards (AquaKonoAngle[AquaKono[1]] + 30.00) degrees)
                              • Unit - Move (Picked unit) instantly to Point[4], facing AquaKonoAngle[AquaKono[1]] degrees
                              • Custom script: call RemoveLocation(udg_Point[4])
                            • Else - Actions
                              • Unit - Kill (Picked unit)
                              • Unit Group - Remove (Picked unit) from AquaKonoGroupDummy[AquaKono[1]]
                          • Custom script: call RemoveLocation(udg_Point[3])
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (AquaKonoGroupDummy[AquaKono[1]] is empty) Equal to True
                        • Then - Actions
                          • Set GenericGroup = (Units within 400.00 of Point[2] matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of AquaKonoCaster[AquaKono[1]])) Equal to True)))
                          • Special Effect - Create a special effect at Point[2] using Objects\Spawnmodels\Other\NeutralBuildingExplosion\NeutralBuildingExplosion.mdl
                          • Special Effect - Destroy (Last created special effect)
                          • Unit Group - Pick every unit in GenericGroup and do (Actions)
                            • Loop - Actions
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • ((Picked unit) is Undead) Equal to True
                                • Then - Actions
                                  • Unit - Cause AquaKonoCaster[AquaKono[1]] to damage (Picked unit), dealing (2.00 x AquaKonoDamage[AquaKono[1]]) damage of attack type Spells and damage type Magic
                                • Else - Actions
                                  • Unit - Cause AquaKonoCaster[AquaKono[1]] to damage (Picked unit), dealing AquaKonoDamage[AquaKono[1]] damage of attack type Spells and damage type Magic
                          • Custom script: call DestroyGroup(udg_GenericGroup)
                          • Custom script: call DestroyGroup(udg_AquaKonoGroupDummy[udg_AquaKono[1]])
                          • Set AquaKonoStage[AquaKono[1]] = 0
                        • Else - Actions
                      • Custom script: call RemoveLocation(udg_Point[2])
                    • Else - Actions
                      • Set AquaKonoDelay[AquaKono[1]] = (AquaKonoDelay[AquaKono[1]] + 0.03)
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • AquaKonoStage[AquaKono[1]] Equal to 2
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • AquaKonoRun[AquaKono[1]] Greater than or equal to AquaKonoDelay[AquaKono[1]]
                        • Then - Actions
                          • Set Point[2] = (Point(AquaKonoX[AquaKono[1]], AquaKonoY[AquaKono[1]]))
                          • Special Effect - Create a special effect at Point[2] using Objects\Spawnmodels\Naga\NagaDeath\NagaDeath.mdl
                          • Special Effect - Set Scale of (Last created special effect) to 2.00
                          • Special Effect - Destroy (Last created special effect)
                          • Set GenericGroup = (Units within 400.00 of Point[2] matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of AquaKonoCaster[AquaKono[1]])) Equal to True)))
                          • Unit Group - Pick every unit in GenericGroup and do (Actions)
                            • Loop - Actions
                              • Set Chance = (Random integer number between 1 and 10)
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • Chance Less than or equal to 5
                                • Then - Actions
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • ((Picked unit) is Undead) Equal to True
                                    • Then - Actions
                                      • Unit - Cause AquaKonoCaster[AquaKono[1]] to damage (Picked unit), dealing (2.00 x AquaKonoDamage[AquaKono[1]]) damage of attack type Spells and damage type Magic
                                    • Else - Actions
                                      • Unit - Cause AquaKonoCaster[AquaKono[1]] to damage (Picked unit), dealing AquaKonoDamage[AquaKono[1]] damage of attack type Spells and damage type Magic
                                • Else - Actions
                                  • Unit - Cause AquaKonoCaster[AquaKono[1]] to damage (Picked unit), dealing AquaKonoDamage[AquaKono[1]] damage of attack type Spells and damage type Magic
                          • Custom script: call RemoveLocation(udg_Point[2])
                          • Custom script: call DestroyGroup(udg_GenericGroup)
                          • Set AquaKonoStage[AquaKono[1]] = 0
                        • Else - Actions
                          • Set AquaKonoRun[AquaKono[1]] = (AquaKonoRun[AquaKono[1]] + 0.03)
                    • Else - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • AquaKonoStage[AquaKono[1]] Equal to 3
                        • Then - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (AquaKonoCaster[AquaKono[1]] is alive) Equal to True
                            • Then - Actions
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • AquaKonoRun[AquaKono[1]] Greater than or equal to AquaKonoDelay[AquaKono[1]]
                                • Then - Actions
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • AquaBoolean[AquaKono[1]] Equal to True
                                    • Then - Actions
                                      • Unit - Set life of AquaKonoCaster[AquaKono[1]] to ((Percentage life of AquaKonoCaster[AquaKono[1]]) - 20.00)%
                                      • Special Effect - Create a special effect attached to the origin of AquaKonoCaster[AquaKono[1]] using war3mapImported\WhiteChakraExplosion.mdx
                                      • Special Effect - Destroy (Last created special effect)
                                    • Else - Actions
                                  • Unit - Cause AquaKonoCaster[AquaKono[1]] to damage AquaKonoDummy[AquaKono[1]], dealing AquaKonoDamage[AquaKono[1]] damage of attack type Spells and damage type Magic
                                  • Set AquaKonoStage[AquaKono[1]] = 0
                                  • Unit - Unpause AquaKonoCaster[AquaKono[1]]
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • AquaKonoChance[AquaKono[1]] Equal to 1
                                    • Then - Actions
                                      • Special Effect - Create a special effect attached to the origin of AquaKonoDummy[AquaKono[1]] using war3mapImported\Shining Flare.mdx
                                      • Special Effect - Destroy (Last created special effect)
                                    • Else - Actions
                                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                        • If - Conditions
                                          • AquaKonoChance[AquaKono[1]] Equal to 2
                                        • Then - Actions
                                          • Special Effect - Create a special effect attached to the origin of AquaKonoDummy[AquaKono[1]] using Abilities\Spells\Human\HolyBolt\HolyBoltSpecialArt.mdl
                                          • Special Effect - Destroy (Last created special effect)
                                        • Else - Actions
                                  • Special Effect - Create a special effect attached to the origin of AquaKonoDummy[AquaKono[1]] using war3mapImported\Valiant Charge Holy.mdx
                                  • Special Effect - Destroy (Last created special effect)
                                  • Animation - Reset AquaKonoCaster[AquaKono[1]]'s animation
                                • Else - Actions
                                  • Set AquaKonoRun[AquaKono[1]] = (AquaKonoRun[AquaKono[1]] + 0.03)
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • AquaKonoRun[AquaKono[1]] Equal to AquaKonoSpeed[AquaKono[1]]
                                    • Then - Actions
                                      • Animation - Play AquaKonoCaster[AquaKono[1]]'s spell two animation
                                    • Else - Actions
                            • Else - Actions
                              • Set AquaKonoStage[AquaKono[1]] = 0
                        • Else - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • AquaKonoStage[AquaKono[1]] Equal to 4
                            • Then - Actions
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • (Current order of AquaKonoCaster[AquaKono[1]]) Equal to (Order(blink))
                                • Then - Actions
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • AquaKonoRun[AquaKono[1]] Greater than or equal to AquaKonoDelay[AquaKono[1]]
                                    • Then - Actions
                                      • Special Effect - Create a special effect attached to the origin of AquaKonoDummy[AquaKono[1]] using war3mapImported\WaterEnchant.mdx
                                      • Special Effect - Destroy (Last created special effect)
                                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                        • If - Conditions
                                          • (AquaKonoDummy[AquaKono[1]] belongs to an ally of (Owner of AquaKonoCaster[AquaKono[1]])) Equal to True
                                        • Then - Actions
                                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                            • If - Conditions
                                              • AquaBoolean[AquaKono[1]] Equal to True
                                            • Then - Actions
                                              • Set GenericPoint = (Position of AquaKonoDummy[AquaKono[1]])
                                              • Unit - Create 1 Peasant Caster for (Owner of AquaKonoCaster[AquaKono[1]]) at GenericPoint facing Default building facing degrees
                                              • Unit - Add Inner Fire (Water of Regeneration) to (Last created unit)
                                              • Unit - Set level of Inner Fire (Water of Regeneration) for (Last created unit) to AquaKonoChance[AquaKono[1]]
                                              • Unit - Order (Last created unit) to Human Priest - Inner Fire AquaKonoDummy[AquaKono[1]]
                                              • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
                                              • Custom script: call RemoveLocation(udg_GenericPoint)
                                            • Else - Actions
                                          • Unit - Set life of AquaKonoDummy[AquaKono[1]] to ((Life of AquaKonoDummy[AquaKono[1]]) + AquaKonoDamage[AquaKono[1]])
                                          • Floating Text - Create floating text that reads (+ + (String((Integer(AquaKonoDamage[AquaKono[1]]))))) above AquaKonoDummy[AquaKono[1]] with Z offset 0.00, using font size 13.00, color (0.00%, 100.00%, 0.00%), and 0.00% transparency
                                          • Floating Text - Set the velocity of (Last created floating text) to 270.00 towards 90.00 degrees
                                          • Floating Text - Change (Last created floating text): Disable permanence
                                          • Floating Text - Change the lifespan of (Last created floating text) to 2.50 seconds
                                          • Floating Text - Change the fading age of (Last created floating text) to 1.50 seconds
                                          • Special Effect - Create a special effect attached to the origin of Elaina_Target[Elaina[1]] using Abilities\Spells\Human\Resurrect\ResurrectTarget.mdl
                                        • Else - Actions
                                          • Unit - Cause AquaKonoCaster[AquaKono[1]] to damage AquaKonoDummy[AquaKono[1]], dealing (0.50 x AquaKonoDamage[AquaKono[1]]) damage of attack type Spells and damage type Magic
                                      • Set AquaKonoStage[AquaKono[1]] = 0
                                    • Else - Actions
                                      • Set AquaKonoRun[AquaKono[1]] = (AquaKonoRun[AquaKono[1]] + 0.03)
                                • Else - Actions
                                  • Set AquaKonoStage[AquaKono[1]] = 0
                            • Else - Actions
 
When working in GUI you'll mostly encounter leaks related to these variable types: Unit Group, Player Group, Point, and Special Effect.

Local variables need to be "nulled" to avoid a leak as well, but the only way to use them in GUI is through Custom Script which people rarely do:
  • Custom script: local unit u = GetTriggerUnit()
  • Custom script: call KillUnit(u)
  • Custom script: set u = null
Global variables do NOT have to be "nulled" since they're permanent. Note that variables made in the Variable Editor are Global variables. The reason for the name is that they can be used in any trigger, so they're accessible from anywhere (globally). Local variables are only accessible from within the trigger that created them (locally).

With that in mind, it's easy to avoid memory leaks in GUI by using these functions:
  • Custom script: call RemoveLocation( udg_PointVariable )
  • Custom script: call DestroyGroup( udg_UnitGroupVariable )
  • Custom script: call DestroyForce( udg_PlayerGroupVariable )
  • Special Effect - Destroy (Last created special effect)
There might be some I'm forgetting about, but the above functions should be your primary solution for dealing with ~90% of your memory leaks.

So even if you're confused about "dealing with memory leaks" as a concept, you can follow the above rule of thumb for safely managing the majority of your memory leaks. Just remember that you don't need to remove/destroy something that is intended to be permanent, you only want to clean up your "trash".
 
Last edited:
Also, one question are udg_UnitVariable = No Unit cause leak?
Strictly speaking, no. But not because setting unit variable to "No unit" would magically remove unit's memory leak. Memory leak definition is "an object allocated in memory which was not deallocated/destroyed and you lost all references to it" - meaning you cannot destroy it anymore and it keeps hanging in the memory.
But you can in most cases remove unit - for example by killing it or by giving it timed life. You can also get units using "Pick every unit" action.
The only cases where units would be considered memory leaks would be for example if you hid a unit and then kept it hidden until the end of the game. That unit would no longer be part of the game, but still be allocated in memory. Or a dummy unit with locust that is not properly removed and has no timed life. Such dummy would keep hanging on in the game.

i didn't want create too much variable because performance issue.
What performance issues?
 
When working in GUI you'll mostly encounter leaks related to these variable types: Unit Group, Player Group, Point, and Special Effect.

Local variables need to be "nulled" to avoid a leak as well, but the only way to use them in GUI is through Custom Script which people rarely do:
  • Custom script: local unit u = GetTriggerUnit()
  • Custom script: call KillUnit(u)
  • Custom script: set u = null
Global variables do not have to be "nulled" since they're permanent. Note that variables made in the Variable Editor are Global variables. The reason for the name is that they can be used in any trigger, so they're accessible from anywhere (globally). Local variables are only accessible from within the trigger that created them (locally).

Anyway, it's pretty easy to avoid memory leaks in GUI. If you're not doing anything too advanced then this is basically all you need to worry about:
  • Custom script: call RemoveLocation( udg_PointVariable )
  • Custom script: call DestroyGroup( udg_UnitGroupVariable )
  • Custom script: call DestroyForce( udg_PlayerGroupVariable )
  • Special Effect - Destroy (Last created special effect)
There might be some I'm forgetting about, but the above functions should be your primary solution for dealing with ~90% of your memory leaks.
So it safe if i use like this or don't null it after all?
  • Untitled Trigger 002
    • Events
    • Conditions
    • Actions
      • Set UnitVariable = (Triggering unit)
      • Custom script: do something
      • Set UnitVariable = No unit
What performance issues?
There are so long loading to load variable espically in Real variable one, because i have 600 of them.
 
So it safe if i use like this or don't null it after all?
  • Untitled Trigger 002
    • Events
    • Conditions
    • Actions
      • Set UnitVariable = (Triggering unit)
      • Custom script: do something
      • Set UnitVariable = No unit
Think back to what I said in my previous post:

These are your main leaks: Unit Group, Player Group, Point, Special Effect, Local variable.

Did you create one of the above?

No -> It's NOT a memory leak.
Yes -> It's a memory leak.

Of course there's some unmentioned cases but I left them out because I believe they're not worth worrying about yet. You'll encounter them if you start working with Hashtables/Local variables/Jass/Lua, etc... in which case you'll probably be following a tutorial that mentions the potential leaks.
 
Last edited:
Think back to what I said:

These are what leak: Unit Group, Player Group, Point, Special Effect, Local variable.

Did you create one of the above? No? Then it's not a memory leak.

Of course there's some unmentioned cases but I left them out because I believe they're not worth worrying about yet. You'll encounter them when you start working with Hashtables/Local variables/Jass/Lua, etc... in which case you'll probably be following a tutorial which mentions the potential leaks.
Alright alright thanks to make it clear? i'm just really confused hahaha
 
Alright alright thanks to make it clear? i'm just really confused hahaha
What type of variable is this?
  • Set UnitVariable = (Triggering unit)
Is it a Unit Group, Player Group, Point, Special Effect, or Local variable?
No.

Does the function it uses -> (Triggering unit) have anything to do with the above variable types?
No.

I'm oversimplifying things here since it can be confusing, but you really just need to memorize a few keywords and how to deal with them.

So setting UnitVariable = "No unit" is unnecessary since it's not a Local variable. Only Local variables need to be "nulled" when you're done with them. You also don't have any temporary objects to destroy/remove which Nichilus went into detail about.
 
Last edited:
There are so long loading to load variable espically in Real variable one, because i have 600 of them.
I don't think this is any issue, to be honest. Most likely you had some triggers that were badly using those variables.
If the issue would be memory allocation for those 600 variables, then I think a more pressing issue would be using arrays, as each array always allocates space for 32768 different values (for indexes from 0 up to 32767).

You could consider:
  • using temp variables if you are having performance issues with world editor rather than during map gameplay. You would basically reuse a set of variables in multiple triggers, decreasing the amount of variables world editor has to track.
  • using local variables when you need to track some stuff in simple triggers. The only disadvantage is that you need to write them using vJASS/lua language inside Custom Script trigger action.
  • rewriting critical systems of your map into vJASS/lua, since GUI transformation to map script creates a lot of bloated code. This, of course, gives you easy access to local variables, but you need to learn vJASS/lua.
 
Back
Top