|
自从写了新的TimerDataSystem以后,发现Handle表回收原理貌似比较有趣~~
于是研究了一下,发现还真是蛮好玩的~~
一开始的触发如下:
[jass]
function Trig________________u_Actions takes nothing returns nothing
local location loc = null
local timer t = null
local unit u = null
local integer i = 0
//local location array Set
loop
exitwhen i >= 5
set loc = Location( 0, i )
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, I2S( H2I( loc ) ) )
call RemoveLocation( loc )
set loc = null
set i = i + 1
endloop
call TriggerSleepAction( 2.0 )
set i = 0
loop
exitwhen i >= 5
set t = CreateTimer()
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, I2S( H2I( t ) ) )
call DestroyTimer( t )
set t = null
set i = i + 1
endloop
call TriggerSleepAction( 2.0 )
set i = 0
loop
exitwhen i >= 5
set u = CreateUnit( Player(0), ‘hfoo’, 0, i * 30, 360 )
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, I2S( H2I( u ) ) )
call RemoveUnit( u )
set u = null
set i = i + 1
endloop
//set i = 0
//loop
// exitwhen i >= 5
// call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, I2S( H2I( Set ) ) )
// call RemoveLocation( Set )
// set Set = null
// call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, Deleted )
// set i = i + 1
//endloop
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, Finish )
endfunction
//===========================================================================
function InitTrig________________u takes nothing returns nothing
set gg_trg________________u = CreateTrigger( )
call TriggerRegisterTimerEventSingle( gg_trg________________u, 0.0 )
call TriggerAddAction( gg_trg________________u, function Trig________________u_Actions )
endfunction
[/jass]
代码大意:
创建5个location,输出它的handleAddress,删除它。
等待2秒(【等待】或【触发、函数结束】之后,Handle表才开始清空)
创建5个timer,输出它的handleAddress,删除它。
等待2秒
创建5个unit,输出它的handleAddress,删除它。
等待2秒
屏幕的输出:
1048669
1048670
1048671
1048672
1048673
1048673
1048672
1048671
1048670
1048669
1048669
1048670
1048671
1048672
1048673
Finish
这样,很快就证明了Handle表回收原理就是按照struct来的。
——使用栈来存储空的HandleAddress,如果栈为空,那么分配新的HandleAddress(新的HandleAddress严格按照递分配增)
然后,听说lightning貌似有特异功能,于是换成了这个:
[jass]
loop
exitwhen i >= 5
set l = AddLightning( CLPB, true, 0.0, 0.0, 0.0, i * 50 )
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, I2S( H2I( l ) ) )
call DestroyLightning( l )
set l = null
set i = i + 1
endloop
call TriggerSleepAction( 2.0 )
set i = 0
loop
exitwhen i >= 5
set l = AddLightning( CLPB, true, 0.0, 0.0, 0.0, i * 50 )
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, I2S( H2I( l ) ) )
call DestroyLightning( l )
set l = null
set i = i + 1
endloop
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, Finish )
[/jass]
输出非常可怕!:
1
1
1
1
1
1
1
1
1
1
Finish
将第一个循环中的call DestroyLightning( l )注释掉。
输出:
1
2
3
4
5
6
6
6
6
6
Finish
我不得不惊讶了……
难道DestroyLightning()有特殊功能?
在函数、等待和触发结束之外,还可以让Handle表直接回收空的Handle?
毕竟在运行DestroyLightning()之后才有的set l = null啊~
又或者说,指向lightning的变量(或者说lightning变身,其实都一样),是不计算变量连接数的吗?
注:
变量连接数——
代表有多少个变量指向一个Handle。
比如:
set u1 = <one>
set u2 = <one>
那么<one>的变量连接数就是2。
在函数、等待和触发结束之后,被执行删除操作的handle会检查变量连接数是否为0,为0则将这个Handle的HandleAddress放入Handle空位表(即栈)中,不为0则不对Handle分配的HandleAddress不做任何操作,无法再次利用,也就是说,泄露了。
而函数、触发和等待并没有自动在执行后将指向被删除的Handle的变量清0的功能……所以说,要在return,endfunction,call TriggerSleepAction()……之前放上个set XXXXX = null
注意!!
以前只说return和endfunction之前清空变量,现在在等待之前也要清空handle变量。
于是实验:
1.让Handle表直接回收空的Handle?
在第一个循环前面增加:
[jass]
set i = 0
loop
exitwhen i >= 5
set l = AddLightning( CLPB, true, 0.0, 0.0, 0.0, i * 50 )
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, I2S( H2I( l ) ) )
set t = CreateTimer()
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, I2S( H2I( t ) ) )
call DestroyTimer( t )
set t = null
call DestroyLightning( l )
set l = null
set i = i + 1
endloop
[/jass]
输出:
1
1048671
1
1048672
1
1048673
1
1048674
1
1048675
1
1
1
1
1
1
1
1
1
1
Finish
看来DestroyLightning()是没有特殊功能了…………
2.将第一个循环的set l = null注释掉…………
输出:
1
1
1
1
1
1
1
1
1
1
Finish
………………天哪…………
lightning居然真的不计算变量连接数……
不对,再换一个形式测试:
[jass]
local lightning l = null
local integer i = 0
local lightning array ls
set i = 0
loop
exitwhen i >= 5
set l = AddLightning( CLPB, true, 0.0, 0.0, 0.0, i * 50 )
set ls = l
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, I2S( H2I( l ) ) )
call DestroyLightning( l )
//set l = null
set i = i + 1
endloop
call TriggerSleepAction( 2.0 )
set i = 0
loop
exitwhen i >= 5
set l = AddLightning( CLPB, true, 0.0, 0.0, 0.0, i * 50 )
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, I2S( H2I( l ) ) )
call DestroyLightning( l )
set l = null
set i = i + 1
endloop
call DisplayTextToPlayer( Player( 0 ), 0.0, 0.0, Finish )
[/jass]
输出:
1
1
1
1
1
1
1
1
1
1
Finish
于是囧了…………看来lightning很可能是用于测试Handle表能否正常运行的测试产物…………
估计失败了(*^__^*) 嘻嘻……
就这样~~
Finish~~ |
|