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

关于排泄(改正一个错误)

[复制链接]
发表于 2010-5-24 17:18:29 | 显示全部楼层 |阅读模式
[trigger]未命名触发器 001
    事件
        时间 - 每 1.00 秒触发事件
    条件
    动作
        单位 - 创建 1 个 步兵 给 玩家1(红色) 在 (矩形区域 000 <预设> 的中心点) ,面向角度为 默认建筑朝向 度
[/trigger]

转换为自定义脚步就是
function Trig____________________001_______u_Actions takes nothing returns nothing
    call CreateNUnitsAtLoc( 1, 'hfoo', Player(0), GetRectCenter(gg_rct______________000), bj_UNIT_FACING )
endfunction
function InitTrig____________________001_______u takes nothing returns nothing
    set gg_trg____________________001_______u = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg____________________001_______u, 1.00 )
    call TriggerAddAction( gg_trg____________________001_______u, function Trig____________________001_______u_Actions )
endfunction

我们看那两个红色的函数
(1)function CreateNUnitsAtLoc takes integer count, integer unitId, player whichPlayer, location loc, real face returns group
    call GroupClear(bj_lastCreatedGroup)
    loop
        set count = count - 1
        exitwhen count < 0
        call CreateUnitAtLocSaveLast(whichPlayer, unitId, loc, face)
        call GroupAddUnit(bj_lastCreatedGroup, bj_lastCreatedUnit)
    endloop
   
return bj_lastCreatedGroup
endfunction


(2)function GetRectCenter takes rect whichRect returns location
   return Location(GetRectCenterX(whichRect), GetRectCenterY(whichRect))
endfunction

type location           extends     handle
bj_lastCreatedGroup是系统自带的全局变量,每次赋值指向的内存地址就会改变,前一个地址可以存东西了,不用排泄。
native Location                 takes real x, real y returns location

Location 是一个COMMOM.J函数,在这里函数GetRectCenter调用了Location ,返回一个Location

是根据这个道理进行排泄么??还是上面说的都是错误的!!大家来看看
发表于 2010-5-24 18:06:54 | 显示全部楼层
记忆中的点排泄只要用变量作为点创建单位,然后删除就可以了。
回复

使用道具 举报

 楼主| 发表于 2010-5-24 18:41:37 | 显示全部楼层
C语言中在一个被调用函数中一般先定义一个变量,然后在返回该变量,所以这里我把location当做一个局部变量对待,不知道是否合适。
回复

使用道具 举报

发表于 2010-5-24 19:15:24 | 显示全部楼层
您还是发疑难解答区吧…………
实在看不下去了…………………

嗯…………才两小时而已。
回复

使用道具 举报

 楼主| 发表于 2010-5-24 19:19:46 | 显示全部楼层
啊!!有错误帮我找找啊!我刚来没多久,什么都不会啊,大家帮帮忙吧!这里人多,发在那边没几个人会看的。 有错误才有进步啊
回复

使用道具 举报

发表于 2010-5-24 19:46:09 | 显示全部楼层
说到C语言的话我就不懂了,但是在Jass里面,一个基本的原则就是在你不需要某个句柄(handle)的时候,就删除它。第二就是所有指向handle的局部变量都要在其失效前set null。

在顶楼中,由于GetRectCenter 返回了一个句柄,而由于你没有用变量来记录它,所以就无法再删除它,这样就造成了内存泄露了。

大概就是这个意思,我的基本功也不扎实。
回复

使用道具 举报

 楼主| 发表于 2010-5-24 19:52:19 | 显示全部楼层
引用第5楼cccty1l于2010-05-24 19:46发表的 :
说到C语言的话我就不懂了,但是在Jass里面,一个基本的原则就是在你不需要某个句柄(handle)的时候,就删除它。第二就是所有指向handle的局部变量都要在其失效前set null。

在顶楼中,由于GetRectCenter 返回了一个句柄,而由于你没有用变量来记录它,所以就无法再删除它,这样就造成了内存泄露了。

大概就是这个意思,我的基本功也不扎实。

假如我用的是全局变量呢??是否要一次一次的删除???
回复

使用道具 举报

发表于 2010-5-24 19:52:36 | 显示全部楼层
没有明确的分区最后版面会很混乱。
回复

使用道具 举报

发表于 2010-5-24 20:05:56 | 显示全部楼层
引用第6楼蚊子于2010-05-24 19:52发表的  :

假如我用的是全局变量呢??是否要一次一次的删除???

这个也分两个情况,比如你用全局变量记录了某个区域的中心点,以后在使用CreateNUnitsAtLoc 时都将此全局变量作为参数传递的话,那就没有问题。而如果你又使用此全局变量记录别的点了,或者又一次调用函数GetRectCenter 将它赋予新的值了(即使与之前的是同一个区域),那么在这之前,还是需要先删除该点的,不然就会有泄露。
回复

使用道具 举报

 楼主| 发表于 2010-5-24 20:12:19 | 显示全部楼层
魔兽中每个具体的东西都占用着分配的一片内存,内存里这片地方的编号就是我们用UnionBug得到的整数。暂称为handle值吧。
假设游戏运行中,整个游戏只有很简单的几个东西:
单位变量 u 指向1048861的地址
单位变量 u2 指向1048861的地址
点变量 p 指向1048862的地址
单位 类型:步兵 handle值1048861 被2个变量连接(u,u2)
点 handle值1048862 被1个变量连接(p)
单位 类型:大法师 handle值1048863 被0个变量连接

我们调用:
单位 - 删除 u
系统找到变量u所代表的单位,读取u所指向的1048861的地址~那个步兵~
好吧,系统找出1048861的地址,清除相应的内存区域并更新游戏。游戏变成:
单位变量 u 指向1048861的地址
单位变量 u2 指向1048861的地址
点变量 p 指向1048862的地址
空 handle值1048861 被2个变量连接(u,u2)
点 handle值1048862 被1个变量连接(p)
单位 类型:大法师 handle值1048863 被0个变量连接
可以看到,1048861的地址已经变为空了,不过u,u2仍连结着1048861。
然后,我们再:
设置 u = (新建 玩家1(红色) 的 骑士 在 p ,面向角度:0.00 度)
这条动作是分2个部分的:
创建1个骑士在p
系统先找到p所代表的点~
然后呢~要在内存中寻找一个能放下东西的空地方-系统找到了编号为1048864的区域:
单位变量 u 指向1048861的地址
单位变量 u2 指向1048861的地址
点变量 p 指向1048862的地址
空 handle值1048861 被2个变量连接(u,u2)
点 handle值1048862 被1个变量连接(p)
单位 类型:大法师 handle值1048863 被0个变量连接
单位 类型:骑士 handle值1048864 被0个变量连接
现在我们再来执行动作的下半部分:
设置u=刚才创建的骑士
之前已经知道了骑士的handle值是1048864,那么就把u指向1048864就好~
单位变量 u 指向1048864的地址
单位变量 u2 指向1048861的地址
点变量 p 指向1048862的地址
空 handle值1048861 被1个变量连接(u2)
点 handle值1048862 被1个变量连接(p)
单位 类型:大法师 handle值1048863 被0个变量连接
单位 类型:骑士 handle值1048864 被1个变量连接(u)

但1048861的地址也是空的,为什么不建立在1048861呢~?
就在于 被1个变量连接(u2) 这一项
1048861原先是一个步兵,我们可以通过变量u2来对他作动作
之后他被删除,于是1048861变成了空,但u2仍是连结在1048861的位置。
如果我们把骑士创建在1048861的位置,那么变量u2在我们没有手动设定的情况下就突然从步兵变成了骑士,显然不合逻辑。
所以暴雪设定一个位置只要有变量连接就不能被占。
变量连接数可以看作是像自定义值一样的绑定在每个handle地址上的整数变量。
设置某变量=某handle地址 时,把该handle地址的变量连接数+1,同时把变量原来指向的handle地址的变量连接数-1
只有满足地址所装东西为空和变量连接数为0两个条件才可以被系统重复利用。
我们在触发中声明一个单位局部变量并连到某单位:单位handle地址的变量连接数+1,在触发结束后局部变量被系统清除了,但单位的handle地址的变量连接数却不会自动-1。。。于是这个地址不能再被利用了,即使单位死后消失。
所以就成了泄漏。。。

关于全局变量不set null的泄漏,不太了解。。。
能知道的是,全局变量不set null的泄漏有2部分。
第一部分,如果我们把1个单位变量指向1个单位,然后删除之。但这个变量仍指向原单位的地址,这个地址在变量指向另一个单位之前就是不可使用的,所以算是泄漏了。但这种"泄漏"是暂时的,与局部变量有本质的区别,想也知道几个全局变量能占多少位置,所以我更愿意把这一部分排除出泄漏的范畴。

第二部分就很诡异了。。。来源未知,原因不明。。。不知道- -
http://we.wechn.com/好像是老狼的教程,他是不是想说明  全局变量不用理他??
回复

使用道具 举报

发表于 2010-5-24 20:22:50 | 显示全部楼层
嗯,比较公认的是不用将全局变量set null,大部分人也是这么做的,但是我还是推荐把它当做局部变量一样处理,好像之前谁也说过貌似全局变量也会有泄露的样子。毕竟多一步也不是很麻烦。
回复

使用道具 举报

 楼主| 发表于 2010-5-24 20:27:38 | 显示全部楼层
哦,我只是想理解排泄的原理,不过感觉有点乱乱的,JASS毕竟跟其他的语言有点不一样
回复

使用道具 举报

发表于 2010-5-24 20:34:28 | 显示全部楼层
嗯,大概就是这些要点了吧,主要就是Jass自己回收垃圾的功能很差。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-24 15:25 , Processed in 0.033183 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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