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

Where is the handle leak in this function ???

Status
Not open for further replies.
Level 12
Joined
Jan 30, 2020
Messages
875
Hello guys.

I have tested my map with a handle counter :

JASS:
function HandleCount takes nothing returns boolean
    local location l=Location(0,0)
    call BJDebugMsg(I2S(GetHandleId(l)-0x100000))
    call RemoveLocation(l)
    set l=null
    return false   
endfunction


function LeakTest takes nothing returns nothing
    local trigger t=CreateTrigger()

    call TriggerRegisterTimerEvent(t,2.00,true)
    call TriggerAddCondition(t,function HandleCount)
    set t=null
endfunction

First of all sorry, I actually didn't put proper spacing on my code, and I am sorry for that.

Next, this trigger is created at map initialization.

After hours of testing, it shows me that the map starts with a handle count of about 700-800
And at the last level (50), it gets close to 100k handles.
I'm not a handle expert, but this is definitely not a leak free behavior.

This is difficult, as everywhere in all my functions, i null local handles, and destroy objects when not used anymore. The only thing I don't care to destroy are the trigger conditions (all my triggers actions have been moved to conditions with no issue).
Fact is, I read in these forums that Conditions have a specific advantage over actions : they get destroyed when the owning trigger is destroyed (don't have the thread link, but it was a compilation of performance benchmarks).

Anyways, I decided to track handle leaks in each and every function I can identify.


The first thing I noticed to increase the handle count slightly but continuously is a custom "Auto Blink" ability that all my units have (buildings and heroes).

here it is :

JASS:
function DoTheBlink takes nothing returns boolean
    local integer order=GetIssuedOrderId()
    local unit theUnit
    local real dX
    local real dY
    local real oX
    local real oY
    local real tX
    local real tY

    if ((order==OrderId("patrol")) or (order==OrderId("smart"))) then
        set theUnit=GetOrderedUnit()
        set oX=GetUnitX(theUnit)
        set oY=GetUnitY(theUnit)
        set tX=GetOrderPointX()
        set tY=GetOrderPointY()
        set dX=oX-tX
        set dY=oY-tY
        if ((dX*dX+dY*dY)>FreeBlinkRange*FreeBlinkRange) then
            call PlayCleanSFX(SFXBlinkCaster , oX , oY, 1.40, 0.00, 0, 1.00)
            call PlayCleanSFX(SFXBlinkTarget , tX , tY, 1.40, 0.00, 0, 1.00)
            call SetUnitPosition(theUnit, tX, tY)
        endif
    endif
    set theUnit=null
    return false
endfunction


function Auto_Blink takes nothing returns nothing
    local integer i=0
    local trigger autoBlink=CreateTrigger()

    loop
      exitwhen i>3
      if ((GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING)) then
          call TriggerRegisterPlayerUnitEvent(autoBlink, Player(i), EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, null)
      endif
      set i=i+1
    endloop
    call TriggerAddCondition(autoBlink, function DoTheBlink)
    set autoBlink=null
endfunction

As far as I can see, there is no reason for that code to leak, so I want to inspect the PlaySFX function I made to control SFX and their duration with a timer :


JASS:
function CleanSFX takes nothing returns nothing
    local timer sfxTimer=GetExpiredTimer()
    local integer parentKey=GetHandleId(sfxTimer)
    local effect sfx=LoadEffectHandle(SFXTable, parentKey, 0)

    call RemoveSavedHandle(SFXTable, parentKey, 0)
    call FlushChildHashtable(SFXTable, parentKey)
    call DestroyEffect(sfx)
    set sfx=null
    call DestroyTimer(sfxTimer)
    set sfxTimer=null
endfunction


function PlayCleanSFX takes string sfxString,real x,real y, real scale, real angle, integer colorindex, real duration returns nothing
    local timer sfxTimer=CreateTimer()
    local effect sfx=AddSpecialEffect(sfxString, x, y)
    local integer parentKey=GetHandleId(sfxTimer)

    call BlzSetSpecialEffectScale(sfx, scale)
    call BlzSetSpecialEffectRoll(sfx, angle)
    if (colorindex!=0) then
        call BlzSetSpecialEffectColor(sfx, Red[colorindex], Green[colorindex], Blue[colorindex])
    endif
    call SaveEffectHandle(SFXTable, parentKey, 0, sfx)
    set sfx=null
    call TimerStart(sfxTimer, duration, false, function CleanSFX)
    set sfxTimer=null
endfunction

But there again, every handle seems to be treated properly to prevent leaks. So I am stuck.

Can anyone identify the source of the leak ? Because thats honestly beyond me at this point.
And trust me most of my functions treat handles in the same way, so if I don't find out, I am condemned to a perpetually leaking map.

Please help me, I reached the limit of my knowledge right there.
 
Status
Not open for further replies.
Top