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

I don't understand what's leaking here.

Status
Not open for further replies.

EdgeOfChaos

E

EdgeOfChaos

This is the trigger I'm using:
  • Return Neutral
    • Events
      • Time - Every 2.00 seconds of game time
    • Conditions
    • Actions
      • Set TempGroup2 = (Units in (Playable map area) matching ((Owner of (Matching unit)) Equal to Player 12 (Brown)))
      • Unit Group - Pick every unit in TempGroup2 and do (Actions)
        • Loop - Actions
          • Set ReturnPoint = (Position of (Picked unit))
          • Set TempGroup = (Units within 1000.00 of ReturnPoint matching (((Owner of (Matching unit)) Not equal to Player 12 (Brown)) and ((Owner of (Matching unit)) Not equal to Player 11 (Dark Green))))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Number of units in TempGroup) Equal to 0
            • Then - Actions
              • Unit - Move (Picked unit) instantly to RevivePoint[(Custom value of (Picked unit))]
              • Unit - Change ownership of (Picked unit) to Player 11 (Dark Green) and Change color
              • Unit - Set life of (Picked unit) to 100.00%
            • Else - Actions
          • Custom script: call DestroyGroup(udg_TempGroup)
          • Custom script: call RemoveLocation(udg_ReturnPoint)
      • Custom script: call DestroyGroup(udg_TempGroup2)
I'm using HandleCounter (http://www.wc3c.net/showthread.php?t=104878), and it claims that I'm leaking 2 handles every time that it runs. But I don't understand why. I'm destroying all my groups and removing all my points...

(Note: RevivePoint is a global variable that is set once)
 
Level 12
Joined
May 22, 2015
Messages
1,051
  • Set TempGroup = (Units within 1000.00 of ReturnPoint matching (((Owner of (Matching unit)) Not equal to Player 12 (Brown)) and ((Owner of (Matching unit)) Not equal to Player 11 (Dark Green))))
This line definitely leaks 1 handle. I looked into it in another thread. The problem is in blizzard.j . The function that line translates to leaks a group handle and you can't prevent it without using JASS.
 

EdgeOfChaos

E

EdgeOfChaos

  • Set TempGroup = (Units within 1000.00 of ReturnPoint matching (((Owner of (Matching unit)) Not equal to Player 12 (Brown)) and ((Owner of (Matching unit)) Not equal to Player 11 (Dark Green))))
This line definitely leaks 1 handle. I looked into it in another thread. The problem is in blizzard.j . The function that line translates to leaks a group handle and you can't prevent it without using JASS.

How so? I'm just using "Units within range matching condition". Isn't that one of the normal unitgroup funcs?

How would you get around using it? I can definitely use JASS, but if that leaks then the JASS GroupEnumUnitsInRange would leak too (as that is all I'm doing, in GUI)

Custom script: call RemoveLocation(udg_RevivePoint) ?

That point array is a global that's set for every unit on map init, I don't want to remove it (and it doesn't leak).
 
Level 13
Joined
Jan 2, 2016
Messages
973
If you do it in jass - it doesn't leak.
The difference is that you will use "GroupEnumUnitsInRange", while GUI is using a BJ function
JASS:
function GetUnitsInRangeOfLocMatching takes real radius, location whichLocation, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

I don't know how does that leak tho... do all handles leak if they are returned? Or perhaps they should've nullified the boolexpr... I don't know.
 
Level 8
Joined
Jan 28, 2016
Messages
486
If you do it in jass - it doesn't leak.
The difference is that you will use "GroupEnumUnitsInRange", while GUI is using a BJ function
JASS:
function GetUnitsInRangeOfLocMatching takes real radius, location whichLocation, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

I don't know how does that leak tho... do all handles leak if they are returned? Or perhaps they should've nullified the boolexpr... I don't know.

Not a 100% sure on this one but is it leaking because the local group that is created is never properly removed? You can't use the DestroyGroup function after the return line as it won't be called.
 
Level 13
Joined
Jan 2, 2016
Messages
973
Not a 100% sure on this one but is it leaking because the local group that is created is never properly removed? You can't use the DestroyGroup function after the return line as it won't be called.

The point of this function is to return a unit group. If it was destroying the group before returning it - it would've been returning a null group, which would be unusable.
However - the group is destroyable:
JASS:
local group g = GetUnitsInRangeOfLocMatching(1000, udg_TempPoint, my_boolexpr)
call DestroyGroup(g)
 
Level 8
Joined
Jan 28, 2016
Messages
486
The point of this function is to return a unit group. If it was destroying the group before returning it - it would've been returning a null group, which would be unusable.
However - the group is destroyable:
JASS:
local group g = GetUnitsInRangeOfLocMatching(1000, udg_TempPoint, my_boolexpr)
call DestroyGroup(g)

Obviously destroying the group before returning it would defeat the purpose and you can't null it either. Then again, the booexpr is taken care of by the function itself which seems odd. Well I guess we'll have to wait for DSG on this one! And like you said, he could use the native GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter) directly.
 
Level 11
Joined
Dec 19, 2012
Messages
411
Dehua_Darbuya got the point, the leaks is caused by the local pointer handle not being nulled. There are few ways to fix it, for your case, there are 2 ways to fix it :

1. Run the conditions inside the unit group instead of running the condition when filtering the unit.

2. Create a new function which fixed the leak for replacement of the function, but that would requires a bit jass knowledge



On a side note : Be careful there picking entire unit inside the playable map is a heavy action, and again picking units within 1000 range for each of the picked unit again. There present high chance that the operation would break (too many units to loop).
 
Level 12
Joined
May 22, 2015
Messages
1,051
If you do it in jass - it doesn't leak.
The difference is that you will use "GroupEnumUnitsInRange", while GUI is using a BJ function
JASS:
function GetUnitsInRangeOfLocMatching takes real radius, location whichLocation, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

I don't know how does that leak tho... do all handles leak if they are returned? Or perhaps they should've nullified the boolexpr... I don't know.

Ya you leak the handle. You don't leak the group unless you don't destroy it yourself after using it (OP is destroying it). It is basically because JASS uses a simple garbage handling system.

This is why you have to null all the local handle variables at the end of a function. The reason it is awkward here is because you can't null the group and then return it, and you can't return (escape the function) and then null it after.

If you were to write this code yourself, you have to use a global variable:
JASS:
function GetUnitsInRangeOfLocMatching takes real radius, location whichLocation, boolexpr filter returns group
    set globalGroup = CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter)
    call DestroyBoolExpr(filter)
    return globalGroup
endfunction

Where globalGroup is a global group variable.


There are a couple other ways to do it, but this is by far the cleanest, I think. It is also nice because the person using it doesn't even have to know about the global variable. One global group variable can be reused in all your system functions that return groups unless there are nested functions.
 
Level 8
Joined
Jan 28, 2016
Messages
486
@DD legionTN: Thanks for clarifying, was starting to second guess myself there for a while. Phew!

@Saus: The whole null-the-variable thing was what I was initially trying to say but I butcher'd it. And about your function, wouldn't it be easier to use the native and keep things in-line rather than write up a custom function in the map header? On second thought, what you got is not a bad idea and would definitely be easy to implement into any map.
 
Level 12
Joined
May 22, 2015
Messages
1,051
@DD legionTN: Thanks for clarifying, was starting to second guess myself there for a while. Phew!

@Saus: The whole null-the-variable thing was what I was initially trying to say but I butcher'd it. And about your function, wouldn't it be easier to use the native and keep things in-line rather than write up a custom function in the map header?

Ya just using the normal natives is easiest and best overall, but I wanted to point out a way to return a group handle without leaking it. If you wrote a similar function in JASS, you would have the same problem as this function unless you use a trick like the one I presented.

It is a good point, though - the natives will just be cleaner and faster.
 
Level 13
Joined
Jan 2, 2016
Messages
973
Well, here is a bummer:
JASS:
function GetUnitsInRangeOfLocAll takes real radius, location whichLocation returns group
    return GetUnitsInRangeOfLocMatching(radius, whichLocation, null)
endfunction
HA! All GUI unit groups using "Get units in range" leak this handle :D
 
Level 12
Joined
May 22, 2015
Messages
1,051
Well, here is a bummer:
JASS:
function GetUnitsInRangeOfLocAll takes real radius, location whichLocation returns group
    return GetUnitsInRangeOfLocMatching(radius, whichLocation, null)
endfunction
HA! All GUI unit groups using "Get units in range" leak this handle :D

LOL! GUI is so dumb sometimes.
 

EdgeOfChaos

E

EdgeOfChaos

So basically using unitgroups in GUI causes leaks. How does Blizzard suck at their own language so much?

That explains so much. I guess I'm coding in JASS from now on.
 
Status
Not open for further replies.
Top