HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Leakage

03-16-2007, 11:30 PM#1
Thunder_Eye
Anyone knows why this is leaking heavily?
(yes I know polarprojection sucks, but im not yet enough interested in the project this code comes from to change it to reals, I also know about the BJ's, but I dont care for the same reason as above)

First 15 uses/arrows are fine, after that it starts lagging alot even thou udg_Arrows is empty and soon freezes wc3
Collapse JASS:
function TargetIsEnemy takes nothing returns boolean
    return (IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetEnumUnit())) == true)
endfunction

function CheckTargetsEmpty takes unit u returns boolean
    return u == null
endfunction

function Trig_Timer_Conditions takes nothing returns boolean
    local unit u = FirstOfGroup(udg_Arrows)
    return u != null
endfunction //just added this function now to prevent this trigger from running every 0.05 sec with no arrows

function ArrowBallMoveDamage takes nothing returns nothing
    local unit pick = GetEnumUnit()
    local location l = GetUnitLoc(pick)
    local unit e
    local group targets = GetUnitsInRangeOfLocMatching(20.00, l, Condition(function TargetIsEnemy))
    local unit target = FirstOfGroup(targets)
    local location arrowpoint
    if CheckTargetsEmpty(target) then
        set arrowpoint = PolarProjectionBJ(l, 2.00, GetUnitFacing(pick))
        call SetUnitPositionLoc(pick, arrowpoint)
        call RemoveLocation(arrowpoint)
        call GroupClear(targets)
    else
        call UnitDamageTarget(pick, target, 300.00, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
        set e = CreateUnitAtLoc(Player(0),'h005',l,0) //impact effect
        call KillUnit(e)
        call KillUnit(pick)
        call GroupRemoveUnit( udg_Arrows, pick )
        call TriggerSleepAction(1.50) //wait so effects animation can be played
        call RemoveUnit(e)
        call RemoveUnit(pick)
    endif
    call RemoveLocation(l)
    call DestroyGroup(targets)
    set l = null
    set e = null
    set pick = null
    set arrowpoint = null
    set targets = null
    set target = null  
endfunction

function Trig_Timer_Actions takes nothing returns nothing
    call ForGroupBJ( udg_Arrows, function ArrowBallMoveDamage )
endfunction

//===========================================================================
function InitTrig_Timer takes nothing returns nothing
    set gg_trg_Timer = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Timer, 0.01 )
    call TriggerAddCondition( gg_trg_Timer, Condition( function Trig_Timer_Conditions ) )
    call TriggerAddAction( gg_trg_Timer, function Trig_Timer_Actions )
endfunction

03-17-2007, 01:56 AM#2
Szythe
At first glance, RemoveLocation(arrowpoint) is missing
EDIT: second glance, you do call it. Although this may still be the problem because if the if is not equal to true, then it wont get cleaned up. Move it to outside the if/then, to where the other cleanup calls are.
03-17-2007, 11:36 AM#3
Thunder_Eye
arrowpoint is never set unless CheckTargetsEmpty is true, so why should I clean a empty variable?
Code:
local arrowpoint
if theboolean == true then
   set arrowpoint = some location
   remove arrowpoint
endif
set arrowpoint = null

*edit*
hmm doesnt this leak?
Collapse JASS:
function PolarProjectionBJ takes >location source<, real dist, real angle returns location
    local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
    local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
    return Location(x, y)
endfunction
03-17-2007, 04:27 PM#4
Szythe
Quote:
Originally Posted by Thunder_Eye
arrowpoint is never set unless CheckTargetsEmpty is true, so why should I clean a empty variable?
Code:
local arrowpoint
if theboolean == true then
   set arrowpoint = some location
   remove arrowpoint
endif
set arrowpoint = null

By setting arrowpoint = null, that is cleaning the value. The RemoveLocation(arrowpoint) is actually destroying the variable, which is created when you declare "local location arrowpoint". Switch around the "set arrowpoint = null" and the "call RemoveLocation(arrowpoint)" with each other.
03-17-2007, 05:52 PM#5
Thunder_Eye
I've only heard the opposite, which also sounds more logical :S
03-17-2007, 07:24 PM#6
Earth-Fury
A handle is a pointer. Its an arrow pointing at the actual data.

Nulling the variable removes the arrow. Destroying the location removes the actual data.
03-18-2007, 12:03 AM#7
Thunder_Eye
Aye. So then my code should be correct?
03-20-2007, 01:13 PM#8
Thunder_Eye
*bump*
03-20-2007, 01:35 PM#9
blu_da_noob
You're not supposed to bump after only two days.


Your problems is that trigger sleep actions kill ForGroup callback threads so your units are never removed. And your condition leaks a handle reference.
03-20-2007, 02:44 PM#10
Thunder_Eye
Quote:
Originally Posted by Rules
Replying to your own thread is known as "double posting." This is not permitted at Wc3Campaigns - use the edit button to make additional content in your post.
You can, however, reply to your own post in order to return ("bump") the thread to the top of the list as long as there has been no reply in over 48 hours, and the thread is less than 1 week old.
meh not really 48 hours, but the thread was on the second page so..
anyway seems the bump was successful

ah right I've heard about that thingy, will fix.

*edit*
thought Execute could fix it, but it still leaks like *****.
could it be the condition handle? :S
Collapse JASS:
function Killing takes nothing returns nothing
    local unit e = udg_e
    local unit pick = udg_pick
    set udg_e = null 
    set udg_pick = null
    call TriggerSleepAction(1.5)
    call RemoveUnit(e)
    call RemoveUnit(pick)
    set e = null 
    set pick = null
endfunction

function ArrowBallMoveDamage takes nothing returns nothing
    local unit pick = GetEnumUnit()
    local location l = GetUnitLoc(pick)
    local unit e = null
    local group targets = GetUnitsInRangeOfLocMatching(20.00, l, Condition(function TargetIsEnemy))
    local unit target = FirstOfGroup(targets)
    local location arrowpoint
    if CheckTargetsEmpty(target) then
        set arrowpoint = PolarProjectionBJ(l, 2.00, GetUnitFacing(pick))
        call SetUnitPositionLoc(pick, arrowpoint)
        call RemoveLocation(arrowpoint)
        call GroupClear(targets)
    else
        call UnitDamageTarget(pick, target, 300.00, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
        set e = CreateUnitAtLoc(Player(0),'h005',l,0)
        call KillUnit(e)
        call KillUnit(pick)
        call GroupRemoveUnit( udg_Arrows, pick )
        set udg_e = e
        set udg_pick = pick
        call ExecuteFunc("Killing")
    endif
    call RemoveLocation(l)
    call DestroyGroup(targets)
    set e = null
    set l = null
    set pick = null
    set arrowpoint = null
    set targets = null
    set target = null  
endfunction

*edit2*
seems like PolarProjection caused most of the leak, this is the current code:
Hidden information:
Collapse JASS:
function PolarProjectionTJ takes location source, real dist, real angle returns location
    local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
    local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
    call RemoveLocation(source)
    set source = null
    return Location(x, y)
endfunction

function TargetIsEnemy takes nothing returns boolean
    return (IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetEnumUnit())) == true)
endfunction

function CheckTargetsEmpty takes unit u returns boolean
    if u == null then
        set u = null
        return true
    else
        set u = null
        return false
    endif
    return u == null
endfunction

function Trig_Timer_Conditions takes nothing returns boolean
    local unit u = FirstOfGroup(udg_Arrows)
    if u != null then
        set u = null
        return true
    else
        set u = null
        return false
    endif
    return u != null
endfunction

function Killing takes nothing returns nothing
    local unit e = udg_e
    local unit pick = udg_pick
    set udg_e = null 
    set udg_pick = null
    call TriggerSleepAction(1.5)
    call RemoveUnit(e)
    call RemoveUnit(pick)
    set e = null 
    set pick = null
endfunction

function ArrowMoveDamage takes nothing returns nothing
    local unit pick = GetEnumUnit()
    local location l = GetUnitLoc(pick)
    local unit e = null
    local group targets = GetUnitsInRangeOfLocMatching(20.00, l, Condition(function TargetIsEnemy))
    local unit target = FirstOfGroup(targets)
    local location arrowpoint
    if CheckTargetsEmpty(target) then
        set arrowpoint = PolarProjectionTJ(l, 2.00, GetUnitFacing(pick))
        call SetUnitPositionLoc(pick, arrowpoint)
        call RemoveLocation(arrowpoint)
        call GroupClear(targets)
    else
        call UnitDamageTarget(pick, target, 300.00, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
        set e = CreateUnitAtLoc(Player(0),'h005',l,0)
        call KillUnit(e)
        call KillUnit(pick)
        call GroupRemoveUnit( udg_Arrows, pick )
        set udg_e = e
        set udg_pick = pick
        call ExecuteFunc("Killing")
    endif
    call RemoveLocation(l)
    call DestroyGroup(targets)
    set e = null
    set l = null
    set pick = null
    set arrowpoint = null
    set targets = null
    set target = null  
endfunction

function Trig_Timer_Actions takes nothing returns nothing
    call ForGroupBJ( udg_Arrows, function ArrowMoveDamage )
endfunction

//===========================================================================
function InitTrig_Timer_Copy takes nothing returns nothing
    set gg_trg_Timer = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Timer, 0.01 )
    call TriggerAddCondition( gg_trg_Timer, Condition( function Trig_Timer_Conditions ) )
    call TriggerAddAction( gg_trg_Timer, function Trig_Timer_Actions )
endfunction


Before this thread, I could only use like 30-40 arrows before the game got unplayable, now I'm up in 200+.

Though something still leaks.. :/
03-21-2007, 08:07 AM#11
blu_da_noob
It's possible your group never has units in and the arrow will never be removed. Try a debug message and check whether or not every arrow is removed (perhaps keep a debug counter of active arrows) and you can check it.
03-21-2007, 03:15 PM#12
Thunder_Eye
Finally some clear results!
It seems the arrow removal is not the problem, but the effects.
They never seem to be removed :S
Will do some further testings to specify what part of the system.

*edit*
Even thou I am now removing the effects using a periodic timer it still leaks!
And now almost even more then before
03-27-2007, 10:58 AM#13
Thunder_Eye
*bump*
03-27-2007, 11:26 AM#14
Rising_Dusk
First of all, you have a double free.
Collapse JASS:
function ArrowMoveDamage takes nothing returns nothing
    local unit pick = GetEnumUnit()
    local location l = GetUnitLoc(pick)
    local unit e = null
    local group targets = GetUnitsInRangeOfLocMatching(20.00, l, Condition(function TargetIsEnemy))
    local unit target = FirstOfGroup(targets)
    local location arrowpoint
    if CheckTargetsEmpty(target) then
        set arrowpoint = PolarProjectionTJ(l, 2.00, GetUnitFacing(pick))
        call SetUnitPositionLoc(pick, arrowpoint)
        call RemoveLocation(arrowpoint)
        call GroupClear(targets)
    else
        call UnitDamageTarget(pick, target, 300.00, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
        set e = CreateUnitAtLoc(Player(0),'h005',l,0)
        call KillUnit(e)
        call KillUnit(pick)
        call GroupRemoveUnit( udg_Arrows, pick )
        set udg_e = e
        set udg_pick = pick
        call ExecuteFunc("Killing")
    endif
    call RemoveLocation(l)
    call DestroyGroup(targets)
    set e = null
    set l = null
    set pick = null
    set arrowpoint = null
    set targets = null
    set target = null  
endfunction
Collapse JASS:
function PolarProjectionTJ takes location source, real dist, real angle returns location
    local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
    local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
    call RemoveLocation(source)
    set source = null
    return Location(x, y)
endfunction
Secondly, you should NOT nullify variables that are arguments to a function.
It's pointless, their references properly maintain themselves.
So get rid of all of those.

Collapse JASS:
function CheckTargetsEmpty takes unit u returns boolean
    if u == null then
        set u = null
        return true
    else
        set u = null
        return false
    endif
    return u == null
endfunction
That should be crunched to --
Collapse JASS:
function CheckTargetsEmpty takes unit u returns boolean
    return u == null
endfunction
The first conditional is pointless.

Next, you are running a function in such a way that the function will be running HUNDREDS of times before the first one finishes. (Thanks to the shittyness of TSA)
Notably, WC3's normaly framerate is 0.033 seconds, so using ANYTHING faster is absolutely silly.
0.01 is faster than anything in WC3 should be, and that means you're running the WHOLE thing 100 times a second.
That's a lot, and the freeze up may be nothing more than computer overload.

Also, you may be breaking WC3.
Collapse JASS:
...
    else
        call UnitDamageTarget(pick, target, 300.00, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
        set e = CreateUnitAtLoc(Player(0),'h005',l,0)
        call KillUnit(e)
        call KillUnit(pick)
        call GroupRemoveUnit( udg_Arrows, pick )
        set udg_e = e
        set udg_pick = pick
        call ExecuteFunc("Killing")
    endif
...
Collapse JASS:
function Killing takes nothing returns nothing
    local unit e = udg_e
    local unit pick = udg_pick
    set udg_e = null 
    set udg_pick = null
    call TriggerSleepAction(1.5)
    call RemoveUnit(e)
    call RemoveUnit(pick)
    set e = null 
    set pick = null
endfunction
That may be breaking WC3 as another form of double free.
If the unit decays within 1.5 seconds, then you're calling RemoveUnit() on an already removed unit.
This not only is beyond unsafe, but if you use H2I() anywhere in the map this can cause handles to be created on eachother's indicies, frying any hopes of your map working.

And probably not the cause, but that BJ you use to create your group leaks a group reference.
Nothing cataclysmic, but anything helps.

My best recommendation is to move from locations to reals and to slow down this timer.
Yes, it will help that much.
03-28-2007, 03:02 PM#15
Thunder_Eye
Quote:
Originally Posted by Thunder_Eye
(yes I know polarprojection sucks, but im not yet enough interested in the project this code comes from to change it to reals, I also know about the BJ's, but I dont care for the same reason as above)

Hmm, maybe I'll have to use coordinates anyway then :/
I'll slow down the timer too.

The reason why I think it is a leak is because if I never fire any shots, It never starts to freeze. And it only starts to lag heavily after lots of arrows has been shot.