• 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.

Group Leak

Status
Not open for further replies.
Level 7
Joined
Aug 19, 2009
Messages
278
I am working with unit groups for the first time. Mostly I try to do things using unit arrays. This is my jass trigger..


JASS:
function Trig_ShadowBall_Dot_Actions takes nothing returns nothing
local unit temp
local real x
local real y
local integer cvalue
local integer tempunitpreset
local group shadowballgroup = CreateGroup()
local integer n1
local integer n = 1
    loop
    exitwhen(n > dhcount)
            if (shadowballcast[n] == 1) then
                set x = GetUnitX(shadowballunit[n])
                set y = GetUnitY(shadowballunit[n])
                call GroupEnumUnitsInRange(shadowballgroup, x, y, 200, Filter(function TrueBoolexpr))
                    loop
                    set temp = FirstOfGroup(shadowballgroup)
                    exitwhen temp == null
                        set cvalue = GetPlayerId(GetOwningPlayer(demonhunters[n]))
                            if (GetPlayerId(GetOwningPlayer(temp)) != cvalue) then
                            if (GetPlayerId(GetOwningPlayer(temp)) != 15) then
                            set tempunitpreset = 0
                            set n1 = ((n*50)-50)
                                loop
                                exitwhen(n1>shadowballhitunitsno[n])
                                    if(shadowballhitunits[n1+((n*50)-50)] == temp) then
                                        set tempunitpreset = 1
                                    endif
                                    set n1 = n1 + 1
                                    set dpstest = dpstest + 1
                                endloop
                                    if (tempunitpreset == 0) then
                                        call UnitDamageTarget( dummyheros[cvalue], temp, 150, true, false, ATTACK_TYPE_MAGIC , DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
                                        set shadowballhitunitsno[n] = shadowballhitunitsno[n] + 1
                                        set shadowballhitunits[shadowballhitunitsno[n]+((n*50)-50)] = temp
                                    endif
                            endif
                            endif
                        call GroupRemoveUnit(shadowballgroup, temp)
                    endloop
                 set shadowballgroup=null
                set shadowballtimer[n] = shadowballtimer[n] - 20
                    if (shadowballtimer[n] <= 0) then
                        set shadowballcast[n] = 0
                        set shadowballunit[n] = null
                        set shadowballhitunitsno[n] = ((n*50)-50)
                    endif
            endif
        set n = n + 1
    endloop
call DestroyGroup(shadowballgroup)
endfunction


Can anyone say if it leaks or not? Is there anyway by which unit arrays can completely replace unit groups. Don't look at the tirggers other than the group part. They are really complicated lol.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
It leaks, but not with the group itself since you're removing it, It leaks with the local variable which remains there

you have to set shadowballgroup = null and temp = null at the end of the trigger
 
Level 7
Joined
Aug 19, 2009
Messages
278
It leaks, but not with the group itself since you're removing it, It leaks with the local variable which remains there

you have to set shadowballgroup = null and temp = null at the end of the trigger

Ya I forgot to do that and add this function

JASS:
function TrueBoolexpr takes nothing returns boolean
return true
endfunction

Thanks
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
about that, you can just place "null" instead of a function that returns true.

call GroupEnumUnitsInRange(shadowballgroup, x, y, 200, null)
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Can someone explain it? I can't think about a reason for that to leak.

EDIT: Check this memory tests with 0.03 event with those functions. I took 2 pictures of each case, at 300- executions and 4000- executions in both cases.


JASS:
globals
    integer count = 0
endglobals

function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    call GroupEnumUnitsInRange(bj_lastCreatedGroup, 0, 0, 200, null)
    set count = count+1
    call DisplayTimedTextToPlayer(Player(0), 0, 0, 1, I2S(count))
endfunction
attachment.php




JASS:
globals
    integer count = 0
endglobals

function TrueBoolexpr takes nothing returns boolean
    return true
endfunction

function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    call GroupEnumUnitsInRange(bj_lastCreatedGroup, 0, 0, 200, Filter(function TrueBoolexpr))
    set count = count+1
    call DisplayTimedTextToPlayer(Player(0), 0, 0, 1, I2S(count))
endfunction
attachment.php

 

Attachments

  • Test Null boolexpr.png
    Test Null boolexpr.png
    100.8 KB · Views: 305
  • Test True boolexpr.png
    Test True boolexpr.png
    367 KB · Views: 296
Level 20
Joined
Jul 14, 2011
Messages
3,213
I get the idea about using the filter for the group actions instead of doing them later. Doesn't apply to many cases, but for those that apply, it's a good idea.

Anyway, in my tests the boolean return took 5 mb's more RAM than null filter. Check last post.
 
Level 7
Joined
Aug 19, 2009
Messages
278
I don't exactly understand the filter(function xxxxx)

Why we write filter and in that way?
What will happen if we write true instead of null?
 
Level 7
Joined
Aug 19, 2009
Messages
278
If something leaks, will the memory seen in task manager keep on going up? And if there is no leak, will the memory stay constant or still rise?
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
thats right, if you have a memory leak, it means that you are creating objects in RAM that you are not cleaning but you unreference them, which means that they cannot be destroyed and are kept in RAM until warcraft 3 is closed. So if you have 1 leak per second, you will have the RAM usage increased by 1*size of that object every second(the size is varying depending on the type, I've heared location is like 100 bytes for instance)
 
I don't exactly understand the filter(function xxxxx)

Why we write filter and in that way?
What will happen if we write true instead of null?

Boolexprs point to a particular function, and it receives the boolean value from it each time the function is executed. The "Filter()" or "Condition()" encloses the code function you are passing. You can't just put the code because it expects a boolexpr/filterfunc/conditionfunc (filterfunc and conditionfunc extend boolexpr, so you should be able to use them interchangeably for boolexpr input), and those are returned through Condition() or Filter().

Putting "true" also wouldn't work because the function expects a boolexpr, but "true" is just a boolean value.

Inputting null basically means there is no filter, so it is kind of the equivalent of having a filter that returns true (since that means all units are included). As Maker said, it was fixed in patch 1.24c:
Patch Notes said:
- Fixed a minor memory leak when using GroupEnum natives.
 
Status
Not open for further replies.
Top