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

[Trigger] Leaks I can't see or find

Status
Not open for further replies.

sentrywiz

S

sentrywiz

This thread is in addition to this thread here: Map Huge Lag (Can't find issue)
It involves my "progress" to solve massive lag in a map of mine.

I have redone the triggers for skillshot missiles, because they had huge parts of triggers and I couldn't find the leaks using nhocklanhox6's memory leak checker

I now have a simpler, cleaner and much more effective missile system but the Leak Finder still reports on lots of leaks, most of them being Group Leaks that I cannot see or find, because the only group I use, I clean.

These are the triggers:


  • Missile Launch
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Ability being cast) Equal to Attack (Staff)
          • (Ability being cast) Equal to Attack (Spear)
          • (Ability being cast) Equal to Attack (Knife)
    • Actions
      • Set missile_PlayerNumber = (Player number of (Owner of (Triggering unit)))
      • Set missile_launcher[missile_PlayerNumber] = (Casting unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to Attack (Staff)
        • Then - Actions
          • Set missile_model[missile_PlayerNumber] = Staff Dummy
          • Set missile_speed[missile_PlayerNumber] = 35.00
          • Set missile_damage[missile_PlayerNumber] = 50.00
          • Set missile_hit_range[missile_PlayerNumber] = ITEM_Staff_Hit[missile_PlayerNumber]
          • Set missile_travel_range[missile_PlayerNumber] = ITEM_Staff_Range[missile_PlayerNumber]
          • Set missile_loc_start[missile_PlayerNumber] = (Position of missile_launcher[missile_PlayerNumber])
          • Set missile_loc_end[missile_PlayerNumber] = (Target point of ability being cast)
          • Unit - Create 1 missile_model[missile_PlayerNumber] for (Owner of missile_launcher[missile_PlayerNumber]) at missile_loc_start[missile_PlayerNumber] facing (Facing of missile_launcher[missile_PlayerNumber]) degrees
          • Set missile_projectile[missile_PlayerNumber] = (Last created unit)
          • Unit Group - Add missile_projectile[missile_PlayerNumber] to Missile_Group
          • Set total_missiles = (total_missiles + 1)
          • Trigger - Turn on Move Missiles <gen>
          • Custom script: call RemoveLocation ( udg_missile_loc_start [udg_missile_PlayerNumber] )
          • Custom script: call RemoveLocation ( udg_missile_loc_end [udg_missile_PlayerNumber] )
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Ability being cast) Equal to Attack (Spear)
            • Then - Actions
              • Set missile_model[missile_PlayerNumber] = Spear Dummy
              • Set missile_speed[missile_PlayerNumber] = 35.00
              • Set missile_damage[missile_PlayerNumber] = 40.00
              • Set missile_critical_chance[missile_PlayerNumber] = ITEM_Spear_Crit[missile_PlayerNumber]
              • Set missile_hit_range[missile_PlayerNumber] = ITEM_Spear_Hit[missile_PlayerNumber]
              • Set missile_travel_range[missile_PlayerNumber] = ITEM_Spear_Range[missile_PlayerNumber]
              • Set missile_loc_start[missile_PlayerNumber] = (Position of missile_launcher[missile_PlayerNumber])
              • Set missile_loc_end[missile_PlayerNumber] = (Target point of ability being cast)
              • Unit - Create 1 missile_model[missile_PlayerNumber] for (Owner of missile_launcher[missile_PlayerNumber]) at missile_loc_start[missile_PlayerNumber] facing (Facing of missile_launcher[missile_PlayerNumber]) degrees
              • Set missile_projectile[missile_PlayerNumber] = (Last created unit)
              • Unit Group - Add missile_projectile[missile_PlayerNumber] to Missile_Group
              • Set total_missiles = (total_missiles + 1)
              • Trigger - Turn on Move Missiles <gen>
              • Custom script: call RemoveLocation ( udg_missile_loc_start [udg_missile_PlayerNumber] )
              • Custom script: call RemoveLocation ( udg_missile_loc_end [udg_missile_PlayerNumber] )
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Ability being cast) Equal to Attack (Knife)
                • Then - Actions
                  • Set missile_model[missile_PlayerNumber] = Knife Dummy
                  • Set missile_speed[missile_PlayerNumber] = 45.00
                  • Set missile_damage[missile_PlayerNumber] = 20.00
                  • Set missile_slow_ratio[missile_PlayerNumber] = ITEM_Knife_Slow[missile_PlayerNumber]
                  • Set missile_hit_range[missile_PlayerNumber] = ITEM_Knife_Hit[missile_PlayerNumber]
                  • Set missile_travel_range[missile_PlayerNumber] = ITEM_Knife_Range[missile_PlayerNumber]
                  • Set missile_loc_start[missile_PlayerNumber] = (Position of missile_launcher[missile_PlayerNumber])
                  • Set missile_loc_end[missile_PlayerNumber] = (Target point of ability being cast)
                  • Unit - Create 1 missile_model[missile_PlayerNumber] for (Owner of missile_launcher[missile_PlayerNumber]) at missile_loc_start[missile_PlayerNumber] facing (Facing of missile_launcher[missile_PlayerNumber]) degrees
                  • Set missile_projectile[missile_PlayerNumber] = (Last created unit)
                  • Unit Group - Add missile_projectile[missile_PlayerNumber] to Missile_Group
                  • Set total_missiles = (total_missiles + 1)
                  • Trigger - Turn on Move Missiles <gen>
                  • Custom script: call RemoveLocation ( udg_missile_loc_start [udg_missile_PlayerNumber] )
                  • Custom script: call RemoveLocation ( udg_missile_loc_end [udg_missile_PlayerNumber] )
                • Else - Actions
  • Move Missiles
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • total_missiles Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
          • For each (Integer A) from 1 to total_missiles, do (Actions)
            • Loop - Actions
              • Set missile_loc_current[(Integer A)] = (Position of missile_projectile[(Integer A)])
              • Set missile_hit_group[(Integer A)] = (Units within missile_hit_range[(Integer A)] of missile_loc_current[(Integer A)] matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of missile_launcher[(Integer A)])) Equal to True)))
              • Set missile_hit_random_unit[(Integer A)] = (Random unit from missile_hit_group[(Integer A)])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Number of units in missile_hit_group[(Integer A)]) Greater than 0
                • Then - Actions
                  • Trigger - Run Missle Damage <gen> (ignoring conditions)
                  • Unit - Remove missile_projectile[(Integer A)] from the game
                  • Set total_missiles = (total_missiles - 1)
                  • Set missile_current_range[(Integer A)] = 0.00
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • missile_current_range[(Integer A)] Less than missile_travel_range[(Integer A)]
                      • (missile_projectile[(Integer A)] is in forbidden_group) Not equal to True
                    • Then - Actions
                      • Set missile_current_range[(Integer A)] = (missile_current_range[(Integer A)] + missile_speed[(Integer A)])
                      • Unit - Move missile_projectile[(Integer A)] instantly to (missile_loc_current[(Integer A)] offset by missile_speed[(Integer A)] towards (Facing of missile_projectile[(Integer A)]) degrees), facing (Facing of missile_projectile[(Integer A)]) degrees
                      • Game - Display to (All players) the text: (String(missile_current_range[(Integer A)]))
                    • Else - Actions
                      • Unit Group - Remove missile_projectile[(Integer A)] from forbidden_group
                      • Unit - Remove missile_projectile[(Integer A)] from the game
                      • Set total_missiles = (total_missiles - 1)
                      • Set missile_current_range[(Integer A)] = 0.00
              • Custom script: call RemoveLocation ( udg_missile_loc_current [GetForLoopIndexA()] )
              • Custom script: call DestroyGroup ( udg_missile_hit_group [GetForLoopIndexA()] )
 
Well, the only variable you need array option for is "total_missiles". The rest can be normal, there won't be any conflicts.

GetForLoopIndexA() -> This calls a new function; use bj_forLoopAIndex instead which is a global variable.

I suggest you used Pick units in group instead of Integer A loop, since you add your missile dummies there anyway. Your indexing method is ancient and there's no recycling involved.

"(missile_loc_current[(Integer A)] offset by missile_speed[(Integer A)]" -> This leaks, it's a new location.
 

sentrywiz

S

sentrywiz

total_missiles I use just to disable the trigger if its 0. It doesn't need array

GetForLoopIndexA() - I use this in remove location to remove location at IndexA. Its valid it didn't give me any errors. Are you saying I should remove location by writing:

Custom script: call RemoveLocation ( udg_missile_loc_current [bj_forLoopAIndex()] ) ?

I don't add missile dummies anywhere I just move them because there can be up to 4 missiles active at one time. The loop just moves them. I found this a better way than picking them in a group, the Leak Finder showed more leaks that way.

(missile_loc_current[(Integer A)] offset by missile_speed[(Integer A)]" -> This leaks, it's a new location.

I remove missile_loc_current at the end of the trigger. Are you saying I need to remove it there once and at the end of the trigger again?
 
Level 5
Joined
May 6, 2013
Messages
125
  • Unit - Move missile_projectile[(Integer A)] instantly to (missile_loc_current[(Integer A)] offset by missile_speed[(Integer A)] towards (Facing of missile_projectile[(Integer A)]) degrees), facing (Facing of missile_projectile[(Integer A)]) degrees
This is the action Pharaoh is referring to. You could essentially simplify it as

  • Unit - Move <missile> instantly to <new Location(missile_loc_current + some offset)> with some facing
the "X offset by y towards z" part creates a new location, which is never removed.

Apart from that, the trigger looks clean to me. The leak finder is far from perfect (finding leaks on compile-time is far from a trivial task) and might tell you about wrong leaks, or maybe some of the BJ's you call leak some handles. Mind posting the leak checkers output?
 

sentrywiz

S

sentrywiz

I changed that, here is how it looks now:

  • Move Missiles
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • total_missiles Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
          • For each (Integer A) from 1 to total_missiles, do (Actions)
            • Loop - Actions
              • Set missile_loc_current[(Integer A)] = (Position of missile_projectile[(Integer A)])
              • Set missile_hit_group[(Integer A)] = (Units within missile_hit_range[(Integer A)] of missile_loc_current[(Integer A)] matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of missile_launcher[(Integer A)])) Equal to True)))
              • Set missile_hit_random_unit[(Integer A)] = (Random unit from missile_hit_group[(Integer A)])
              • Custom script: set bj_wantDestroyGroup = true
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Number of units in missile_hit_group[(Integer A)]) Greater than 0
                • Then - Actions
                  • Trigger - Run Missile Damage <gen> (ignoring conditions)
                  • Unit - Remove missile_projectile[(Integer A)] from the game
                  • Set total_missiles = (total_missiles - 1)
                  • Set missile_current_range[(Integer A)] = 0.00
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • missile_current_range[(Integer A)] Less than missile_travel_range[(Integer A)]
                      • (missile_projectile[(Integer A)] is in forbidden_group) Not equal to True
                    • Then - Actions
                      • Set missile_current_range[(Integer A)] = (missile_current_range[(Integer A)] + missile_speed[(Integer A)])
                      • Set missile_hit_loc[(Integer A)] = (missile_loc_current[(Integer A)] offset by missile_speed[(Integer A)] towards (Facing of missile_projectile[(Integer A)]) degrees)
                      • Unit - Move missile_projectile[(Integer A)] instantly to missile_hit_loc[(Integer A)], facing (Facing of missile_projectile[(Integer A)]) degrees
                      • Custom script: call RemoveLocation ( udg_missile_hit_loc [GetForLoopIndexA()] )
                    • Else - Actions
                      • Unit Group - Remove missile_projectile[(Integer A)] from forbidden_group
                      • Unit - Remove missile_projectile[(Integer A)] from the game
                      • Set total_missiles = (total_missiles - 1)
                      • Set missile_current_range[(Integer A)] = 0.00
              • Custom script: call RemoveLocation ( udg_missile_loc_current [GetForLoopIndexA()] )
              • Custom script: call DestroyGroup ( udg_missile_hit_group [GetForLoopIndexA()] )
And here is what the Leak Finder shows (with the changes) :

NOTE: This is only from casting one missile.

-lf command

leak lf.jpg

-lc command

leak lc.jpg
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
In the trigger shown above I only see one leak

  • Set missile_hit_loc[(Integer A)] = (missile_loc_current[(Integer A)] offset by missile_speed[(Integer A)] towards (Facing of missile_projectile[(Integer A)]) degrees)
missile_hit_loc already has a value assigned to it which gets dereferenced.
 

sentrywiz

S

sentrywiz

In the trigger shown above I only see one leak

  • Set missile_hit_loc[(Integer A)] = (missile_loc_current[(Integer A)] offset by missile_speed[(Integer A)] towards (Facing of missile_projectile[(Integer A)]) degrees)
missile_hit_loc already has a value assigned to it which gets dereferenced.

I don't get it.
Before that they told me that I was not using a var for the location with offset, so I put a var with that location and it still leaks now? How does it leak, can you explain that?

missile_hit_loc doesn't have a value before I give it. Maybe you got confused with missile_loc_current, which I use as the current position of the missile.

Don't use integer A / B. They are slower and less efficient than using your own custom integer.

Take a look at my tutorial Things you should know when using triggers / gui.

That's a good tip. I'll remake the trigger with my own integer. Though this doesn't have anything with the leaks, which the Leak Finder still finds so even though this might improve efficiency it won't matter if leaks build up over time.

EDIT:

Can anyone tell me why does the Leak Finder find so many leaks from Select unit from random when I clean that and it shouldn't leak?
Or can you examine the screenshots I uploaded earlier to tell me where the leaks originate?
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
You should really get rid of those arrays and use a temp location variable since you do not store those locations long term. It would make your code faster and easier to read / manage.

The leak your checker is picking up is not a location leak. Your locations are fine.

It may be picking up a handle leak when using (Number of units in missile_hit_group[(Integer A)]). I believe that leaks a handle that can't be fixes using GUI.
This leaks a unit group if you do not place the bj_wantdestroygroup above it. (Random unit from missile_hit_group[(Integer A)])

You should also store this as you use it more than once. (Owner of missile_launcher[(Integer A)]))

You should also change the indexing you use to an indexed array method. Your current one can bug.

Show us all triggers relating to this.
 

sentrywiz

S

sentrywiz

You should really get rid of those arrays and use a temp location variable since you do not store those locations long term. It would make your code faster and easier to read / manage.

The leak your checker is picking up is not a location leak. Your locations are fine.

It may be picking up a handle leak when using (Number of units in missile_hit_group[(Integer A)]). I believe that leaks a handle that can't be fixes using GUI.
This leaks a unit group if you do not place the bj_wantdestroygroup above it. (Random unit from missile_hit_group[(Integer A)])

You should also store this as you use it more than once. (Owner of missile_launcher[(Integer A)]))

You should also change the indexing you use to an indexed array method. Your current one can bug.

Show us all triggers relating to this.

So the leak finder is picking up stuff that GUI can't clean. Oh that's just neat. Thanks I might store that as well.

But it doesn't bug, at least not for me as of yet.

Those are ALL the triggers related to this. I'm not hiding any triggers. Those two are the only triggers for moving the missile. The rest are misc triggers, for multiboard, revival, masteries. If you want to see all the rest of the triggers, follow the link provided above to the other thread and you can download the map and see for yourself.

That map however uses group instead a for loop for moving missiles. I made this in hope that it wouldn't cause massive lag so that I can update the map however it seems this is more of a problem that I imagined.

in your loop, you run the trigger Missile Damage
so show me the trigger of missile damage

That's just a blank trigger. I haven't gotten to making that one yet because what's the point if this one doesn't work properly.
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
JASS:
function CountUnitsInGroup takes group g returns integer
    // If the user wants the group destroyed, remember that fact and clear
    // the flag, in case it is used again in the callback.
    local boolean wantDestroy = bj_wantDestroyGroup
    set bj_wantDestroyGroup = false

    set bj_groupCountUnits = 0
    call ForGroup(g, function CountUnitsInGroupEnum)

    // If the user wants the group destroyed, do so now.
    if (wantDestroy) then
        call DestroyGroup(g)
    endif
    return bj_groupCountUnits
endfunction

CountUnitsInGroup does not leak
 

sentrywiz

S

sentrywiz

JASS:
function CountUnitsInGroup takes group g returns integer
    // If the user wants the group destroyed, remember that fact and clear
    // the flag, in case it is used again in the callback.
    local boolean wantDestroy = bj_wantDestroyGroup
    set bj_wantDestroyGroup = false

    set bj_groupCountUnits = 0
    call ForGroup(g, function CountUnitsInGroupEnum)

    // If the user wants the group destroyed, do so now.
    if (wantDestroy) then
        call DestroyGroup(g)
    endif
    return bj_groupCountUnits
endfunction

CountUnitsInGroup does not leak

What is this for?
 
Status
Not open for further replies.
Top