| 11-01-2010, 07:53 PM | #1 |
I was wondering if this dummy caster creation code leaked a unit handle. Specifically at the end of CreateCaster(): JASS:library DummyCast function CreateCaster takes player owner, real x, real y, integer abilid, integer level returns unit local unit dummy = CreateUnit(owner,'dCAS',x,y,0) call UnitAddAbility( dummy, abilid) call SetUnitAbilityLevel( dummy, abilid, level) call UnitApplyTimedLife( dummy, 0, 2) //Am I leaking a unit handle here? return dummy endfunction function CastAbilityTarget takes player caster, unit target, real x, real y, integer abilid, integer abillvl, string order returns nothing local unit dummy = CreateCaster(caster, x, y, abilid, abillvl) call IssueTargetOrder(dummy,order,target) set dummy = null endfunction endlibrary If it does leak, is there a better strategy? |
| 11-01-2010, 08:08 PM | #2 |
CreateCaster leaks. JASS:function CreateCaster takes player owner, real x, real y, integer abilid, integer level returns unit set bj_lastCreatedUnit = CreateUnit(owner,'dCAS',x,y,0) call UnitAddAbility(bj_lastCreatedUnit, abilid) call SetUnitAbilityLevel(bj_lastCreatedUnit, abilid, level) call UnitApplyTimedLife(bj_lastCreatedUnit, 0, 2) return bj_lastCreatedUnit endfunction You could use another global unit variable if you're already using that one. |
| 11-01-2010, 08:18 PM | #3 |
Thanks for the fast reply! That worked just fine. I'm assuming that global var will not be conflicted over when calling CastAbilityTarget() multiple times (in say, a loop)? |
| 11-01-2010, 08:23 PM | #4 |
Na, it should be fine. You prolly want to cleanup the unit in CastAbilityTarget though. call UnitApplyTimedLife(dummy, 'BTLF', 5.) after the IssueTargetOrder should be fine. |
| 11-01-2010, 08:30 PM | #5 |
I have a call to that already in the CreateCaster is that fine? I also do not have any buff or ability with the id 'BTLF' |
| 11-01-2010, 08:34 PM | #6 |
Oh whoops, I missed that. Yeah that's fine and you don't need a buff matching the ID. |
| 11-01-2010, 08:54 PM | #7 |
To clarify, the code was not leaking a unit handle since the unit got cleaned up when its expiration timer expired, but it was leaking a handle index: due to a bug, local variables are not "set to null" when a function finishes, so the handle index still has a record of those variables pointing to it and does not get recycled because of that. As a result, new indexes must be allocated when new handles are created. By the way, when dealing with dummy casters, I find xecast incredibly useful, I encourage you to take a look at it. |
| 11-05-2010, 01:37 AM | #8 |
The variable dummy inside the function CreateCaster can't be nullified. Leak, or not? why don't you... JASS:function CastAbilityTarget takes player caster, unit target, real x, real y, integer abilid, integer abillvl, string order returns nothing local unit dummy = CreateUnit(caster,'dCAS',x,y,0.) call UnitAddAbility( dummy, abilid) call SetUnitAbilityLevel( dummy, abilid, abillvl) call UnitApplyTimedLife( dummy, 'BTLF', 2) call IssueTargetOrder(dummy,order,target) set dummy = null endfunction ? |
| 12-01-2010, 12:03 PM | #9 |
Because parameters do not leak handle indexes, this would solve the problem easily: JASS:private function HiddenCreate takes unit u, integer abilid, integer level returns unit call UnitAddAbility(u, abilid) call SetUnitAbilityLevel(u, abilid, level) call UnitApplyTimedLife(u, 'BTLF', 2.) return u endfunction function CreateCaster takes player owner, real x, real y, integer abilid, integer level returns unit return HiddenCreate(CreateUnit(owner, 'dCAS', x, y, 0.)) endfunction However, there is an amazing way discovered to cast spells instantly without having to wait for the dummy to turn to face the target, meaning the same dummy can be used for every spell in the game. It's not much of a secret. |
