找回密码
 点一下
查看: 2404|回复: 12

jass排泄的疑问【已解决】

[复制链接]
发表于 2012-7-30 11:01:25 | 显示全部楼层 |阅读模式
GetUnitLoc()返回点需要排泄
如果写了一个返回单位的函数,比如获得英雄最近的单位的函数,它返回的单位有没有占用了内存了吗?如果多次都是返回同一个单位,虽然没有创建单位,但是在那个函数里用到了
local unit u,最后返回u,这样这个局部变量u一直在堆积,要怎么排泄才好
这个函数能和GetTriggerUnit()一样不用排泄吗?但是我写的那个函数中有local unit u ,就创建了局部变量,
 楼主| 发表于 2012-7-30 11:33:28 | 显示全部楼层

回 美味豆沙包 的帖子

美味豆沙包:GetTriggerUnit是native函数,没什么参考价值

楼主可以看看blizzard.j里面的bj函数
例如CreateNUnitsAtLoc,它是将创建的单位先赋值给bj_lastCreatedGroup这个全局变量,然后再return bj_lastCreatedGroup的 (2012-07-30 11:22)
用一个新的局部变量记录,用完后再set null可以吗?
回复

使用道具 举报

发表于 2012-7-30 11:33:51 | 显示全部楼层
最后返回u的话,那个u是没办法排泄的
所以你需要用到其他的办法来解决返回值问题

方法一:用一个全局变量来临时存放返回值,然后返回这个全局变量

方法二:使用参数变量(takes XX)来存放返回值,然后返回这个参数变量

注:全局变量可以随时修改,参数变量是不会增加引用数的

GetTriggerUnit是native函数,没什么参考价值

楼主可以看看blizzard.j里面的bj函数,例如CreateNUnitsAtLoc
它是将创建的单位先赋值给bj_lastCreatedGroup这个全局变量,然后再return bj_lastCreatedGroup的

注:返回的对象需不需要排泄和该函数无关
如果在返回时泄露了,那么返回后你也不可能排除这个泄露,这不是函数的泄露,而是局部变量的泄露
回复

使用道具 举报

 楼主| 发表于 2012-7-30 11:44:38 | 显示全部楼层

回 美味豆沙包 的帖子

美味豆沙包:如果已经返回了,你还怎么set null呢? (2012-07-30 11:34)
比如说
local unit u=getunit()
……
set u=null
回复

使用道具 举报

发表于 2012-7-30 11:50:12 | 显示全部楼层

回 weituotian 的帖子

weituotian:用一个新的局部变量记录,用完后再set null可以吗?(2012-07-30 11:33)嬀/color]
如果已经返回了,你还怎么set null呢?

魔兽里面的一个对象(如:单位,单位组,点......)每当它被赋值给一个变量的时候,它的引用数就会加一;
而当这个变量改变值的时候,它原来所指向的对象的引用数就会-1;
如果在这个对象被删除之后,它的引用数不为0,那么它所占的内存空间就不会被释放...也就是我们常说的“记忆体遗失”(内存泄露)

set null...就是设置变量为空,如果是单位就是设为“没有单位”,目的是清空引用数
如果是对象类型的局部变量,如果你不想泄露,就需要set null
如果是全局变量则必要不大...因为当这个变量被再次赋值的时候,它的引用关系就可以改变了

如果有2个变量指向这个对象,那么它的引用数就是2;如果有3个变量指向这个对象,那么它的引用数就是3.
如果返回一个局部变量,是没办法set null的,所以就一定会泄露......
哪怕你用一个新的局部变量将返回值存起来,也只能增加这个对象的引用数,而并不能减少它
回复

使用道具 举报

发表于 2012-7-30 11:53:40 | 显示全部楼层
weituotian:比如说
local unit u=getunit()
……
set u=null (2012-07-30 11:44)
楼层好奇怪……是我眼花了吗。。。
顶楼:如果写了一个返回单位的函数,比如获得英雄最近的单位的函数
这句话是LZ你自己写的,如果
local unit u = xxx
set u = null

这么做之后LZ要如何返回那个u?即便返回了也不是获取到的单位而是null

所以常用的方法板凳已经给了~
如果用全局变量的话,也不用专门去准备一个临时变量,直接用bj_lastCreatedUnit即可~ 这个是BJ初始创建好的全局,跟自己创建是一样的
回复

使用道具 举报

发表于 2012-7-30 11:54:31 | 显示全部楼层

回 weituotian 的帖子

weituotian:比如说
local unit u=getunit()
……
set u=null(2012-07-30 11:44)嬀/color]
如果getunit函数没有泄露,自然没有问题
如果getunit函数在返回时已经泄露了(返回局部变量),那么即使用一个新的局部变量将其存放起来也不能将泄露排除

因为,如果泄露了,那么对象的引用数一定大于1
虽然set u=null可以将引用数-1
但是其实之前的local unit u=getunit已经将引用数+1了
也就是说还是大于1...
回复

使用道具 举报

 楼主| 发表于 2012-7-30 11:55:07 | 显示全部楼层
我拿出实例好一点
function GetUnitById takes integer unitid returns unit //通过单位id获得单位
    local unit ru=null
    local unit u=null
    local group g=CreateGroup()
    call GroupEnumUnitsInRange(g,0,0,999999,null)
    loop
        set u=FirstOfGroup(g)
        exitwhen u==null
        if(GetUnitTypeId(u)==unitid)  then
            set ru=u
        endif
        call GroupRemoveUnit(g,u)
    endloop
    call DestroyGroup(g)
    set g=null
    return ru
endfunction

function others takes nothing returns nothing
local unit u=GetUnitById ('hfoo')
call DoSomething()
set u=null
endfunction
这个不知道有没有排泄的问题,在下面

function GetPlayersAllies takes player whichPlayer returns force
 local force f = CreateForce()
 call ForceEnumAllies(f, whichPlayer, null)
 return f
endfunction

 中local force f = CreateForce()创建了新势力,所以在调用后要清除
而GetUnitById()并没有创建单位,这样可以吗?
回复

使用道具 举报

 楼主| 发表于 2012-7-30 12:04:27 | 显示全部楼层

回 chyj4747 的帖子

chyj4747:这句话是LZ你自己写的,如果
local unit u = xxx
set u = null

....... (2012-07-30 11:53)
local unit u = GetUnit()
call dosomething()
set u = null
这个是新建立的局部变量,记录原来函数传回的单位
回复

使用道具 举报

发表于 2012-7-30 12:06:49 | 显示全部楼层

回 weituotian 的帖子

weituotian:
我拿出实例好一点
function GetUnitById takes integer unitid returns unit //通过单位id获得单位
    local unit ru=null
    local unit u=null
    local group g=CreateGroup()
.......
有一个局部变量泄露
    return ru

这里return了ru,但是ru并没有set null,自然就泄露了

虽然你之后
local unit u=GetUnitById ('hfoo')

set u=null
但是并没有解决这个泄露
因为这里是“局部变量泄露”而并不是“单位泄露”
实际上单位不需要排泄,因为在单位死亡,尸体腐烂之后,系统会自动将其删除
而set null解决的是局部变量的泄露,也就是“引用数”的问题
局部变量的生命周期是在“函数运行时”,如果之前的函数已经泄露了,那么之后的函数就再也无法解决了
回复

使用道具 举报

发表于 2012-7-30 12:17:36 | 显示全部楼层

回 weituotian 的帖子

weituotian:local unit u = GetUnit()
call dosomething()
set u = null
这个是新建立的局部变量,记录原来函数传回的单位
.......(2012-07-30 12:04)嬀/color]
local unit u储存的是那个单位,而不是getunit函数中的的那个局部变量ru
(这里是返回值,而不是返回引用,JASS没这功能)
但是我们要解决的是“局部变量ru泄露”的问题,而不是“单位泄露”的问题
所以local unit u并不能解决这个泄露,明白了吗?
回复

使用道具 举报

 楼主| 发表于 2012-7-30 12:18:10 | 显示全部楼层
原来是局部变量泄露,非常感谢,我弄明白了
回复

使用道具 举报

发表于 2012-7-30 23:30:36 | 显示全部楼层
问一下
local unit u=GetTriggerUnit()
call dosomething()
set u=null
这样子有没有必要?
如果想要使用u来储存返回的单位,那么set u=null是有必要的
因为这个局部变量u也是会泄露的
如果不使用局部变量就可以不set null...

单位是不需要排泄的...只需要注意储存单位的局部变量不要泄露就好
(也就是说“单位”不需要“删除”,局部变量需要set null)

相对而言,点、单位组、玩家组等对象就需要删除了
为了排泄,你不仅需要“删除点”,还需要set null来解决局部变量的泄露

整数、实数...那些不能将null赋值给它的变量都不需要排泄和set null

嗯,差不多就是这样了

@weituotian
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-5-2 11:34 , Processed in 0.073298 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表