请选择 进入手机版 | 继续访问电脑版

 找回密码
 点一下
查看: 7286|回复: 55

Union Bug 1个需要注意的地方

[复制链接]
发表于 2009-5-3 18:07:27 | 显示全部楼层 |阅读模式
[jass]globals
string a
boolean b//和定义类型无关
endglobals
function aa takes nothing returns nothing
local integer a
local unit b    //最后定义为handle类型
set a=-174        //等价于 set b=I2U(-174)     所以弹错
endfunction
function bb takes nothing returns nothing
local unit b            
local integer a  //最后定义为integer类型
set a=-174       //不等价于 set b=I2U(-174)     所以不弹错
endfunction[/jass]

[jass]call aa()//弹错[/jass][jass]
call bb()//正常调用[/jass]

之前头目那贴 也有提到最后声明的类型 是为 这些变量的类型
如果定义成handle 那就需要set null 定义成integer那就不需要 set null或者set 0

前天遇到某地图使用hash系统弹错 原因就是最后定义为handle 而返回负值 等效了I2U(负数)  如aa()

Union Bug赋值弹出bug.w3x

20 KB, 下载次数: 34

评分

参与人数 1威望 +1 收起 理由
血戮魔动冰 + 1 啦啦啦~~

查看全部评分

发表于 2009-5-3 19:22:54 | 显示全部楼层
为了排泄一般都设为null
不过我使用的是将整数设为0

头目也有大概的说明
在22L
回复

使用道具 举报

 楼主| 发表于 2009-5-3 19:38:36 | 显示全部楼层
ls似乎没理解我的意思

..如果定义为handle 那样需要set null
而且不能设置负数..否则会弹错..
看function aa
回复

使用道具 举报

发表于 2009-5-3 19:44:40 | 显示全部楼层
哦……
确实没这么想
但是谁会设成负数……

……
我还真设过……
回复

使用道具 举报

发表于 2009-5-3 19:45:43 | 显示全部楼层
恩啊,一般的确不会去设置为负的吧……
回复

使用道具 举报

发表于 2009-5-3 19:59:19 | 显示全部楼层
除非是用做某个默认情况
做Location数组时空项用了-1
倒是没注意……
回复

使用道具 举报

发表于 2009-5-3 20:49:31 | 显示全部楼层
所以说~~始终将最后一个覆盖变量声明为integer~~即安全又无内存泄露~~甚至不需要=0~~
回复

使用道具 举报

发表于 2009-5-3 21:20:04 | 显示全部楼层
前面的handle型也不用排泄?
自动清空了么?
回复

使用道具 举报

 楼主| 发表于 2009-5-3 21:38:43 | 显示全部楼层
定义为整数就不需要set null
但删除还是要的。。

设置负很多啊。。。。比如那些hash  系统。。很多都设置无时返回-1
回复

使用道具 举报

发表于 2009-5-3 21:45:54 | 显示全部楼层
引用第7楼疯人¢衰人于2009-05-03 21:20发表的  :
前面的handle型也不用排泄?
自动清空了么?

显然你没有全部看完我那个关于Union的帖子阿~~我在第二页写了~~如果最后覆盖的那个变量设定为非Handle类型(其实就只有integer)~~那么jass根本不会追踪它的变量连接数~~函数结束后必定直接释放~~所以不需要考虑set null或者set 0的问题~~


handle这种东西本身由于涉及到对象的可达性才会去追踪变量连接数的~~而Integer并不涉及任何对象~~所以jass在设计的时候根本没有整这一部分~~当然本身销毁对象这一步还是要自己做~~但此时对象和变量已经没有直接关系了~~

然后我推荐Union Bug写法的原因有两个~~
一个是转换效率高~~其实Union Bug的所谓“转换”并没有进行任何变量传递~~仅仅是同一个数据的不同读取方式而已~~而Return Bug涉及到两个变量之间的传值~~甚至还要跨越 一个函数~~
第二个是其实Return Bug有时候会出现不可避免的内存泄露~~而Union Bug只要调整下Integer的位置甚至根本就不用去考虑这个问题~~
回复

使用道具 举报

发表于 2009-5-3 21:57:55 | 显示全部楼层
引用第8楼linzefei于2009-05-03 21:38发表的  :
定义为整数就不需要set null
但删除还是要的。。

设置负很多啊。。。。比如那些hash  系统。。很多都设置无时返回-1

嗯,我之前些的Hash是在出现错误的时候返回-1,现在已经全部修改为0了。
但是要注意呀,这个返回错误的步骤可不是摆设,至少在存储数据之前判断一下是不是返回了-1或0呀。
回复

使用道具 举报

 楼主| 发表于 2009-5-3 22:35:02 | 显示全部楼层
我那个也要改掉了。。。等下都去改0。。
0位置就不用了
回复

使用道具 举报

发表于 2009-5-3 22:43:55 | 显示全部楼层
一句题外话~~话说发现LS的头像某个版本是X~~
回复

使用道具 举报

发表于 2009-5-3 22:45:05 | 显示全部楼层
引用第9楼Renee于2009-05-03 21:45发表的  :


显然你没有全部看完我那个关于Union的帖子阿~~我在第二页写了~~如果最后覆盖的那个变量设定为非Handle类型(其实就只有integer)~~那么jass根本不会追踪它的变量连接数~~函数结束后必定直接释放~~所以不需要考虑set null或者set 0的问题~~


.......
后面看了
不过看的有些混乱了
Handle型式连接数为0时清空的?
如果是这样
那么如果我们创建一个新的handle变量
那么它的连接数是0
用一次加一次
那么当我们在Unionbug中创建一个新handle呢
它的连接数是多少?
比如Local location= Location(0,0)
handle的具体内容不是很懂……
回复

使用道具 举报

发表于 2009-5-3 23:15:06 | 显示全部楼层
e~~我详细解释下吧~~

所谓变量连接数~~

你知道handle表是war3拿来定位对象的一个表~~很多对象在表中有其唯一标识也就是handle值~~

这个表呢~~每个元素都是一个结构~~存储目的对象的实际内存地址和引用了该对象的变量数量~~

比如某单位handle值1892323~~然后这个单位被赋给了某个unit变量A~~那么变量A的值就是1892323~~那么handle表中的1892323这个元素的变量连接数就+1~~

但是这样下去的话随着对象的增加~~handle表内的元素会不断增加~~虽然每个元素所占空间不大但是积累起来的内存泄露也是很惊人的~~

于是jass就有个机制也就是表位复用~~比如我先删除1892323这个表位所对应的单位~~然后jass会判断这个表位的变量连接数是不是被清零了~~如果发现没有任何变量指向这个表位~~那么这个表位的结构就可以被复用~~比如我下次新建一个单位的时候还是用的1892323这个表位~~

你想既然是每当有一个新变量指向这个表位~~这个表位的变量连接数就+1~~那么减少连接数的方法呢?~~自然是让原本指向它的变量指向其他值~~当然~~除了null以外的值它都是handle表位(正数)~~或是造成非法操作的值(负数)~~所以就算改成其他正整数也会使得其他handle表位遭殃~~因此set null是最好的减少变量连接数方法~~

这很好是吧~?~~问题是jass有一个疏忽~~我们都知道局部变量只生存于函数内~~函数结束后就会被销毁~~问题是如果某个局部变量在函数结束后消失~jass却并不会一并将它指向的对象的变量连接数-1~~于是就很糟糕了~~这个是jass的漏洞~~其他编程语言都会自动减少变量连接数的~~(这里我们只考虑局部变量,因为全局变量并没有被销毁这一说而且连接数的计算方式不同,并没有这个问题)~~于是我们这个局部变量完蛋以后~~它原本所指向的那个表位的变量连接数无法减到0了~~于是那个表位就永远挂在那里造成内存泄露~~直到地图退出~~


于是我们才提倡手动将局部变量set null~~然后为什么Union Bug将最后一个Union变量声明为integer就没这问题呢?~~因为handle表位的变量连接数只追踪handle型变量(其实也包括string等等因为它们也有handle,所以除外的只有integer)~~当任何一个handle类型变量被赋值为某个正整数的时候~~该正整数的handle表位的变量连接数就+1~~拿前面那个1892323为例~~如果某个handle类型变量(不一定得是unit类型)的值被设为1892323的时候~~这个表位的变量连接数就自动+1~~然而jass是不可能去追踪integer型变量的~~因此一旦将最后一个Union变量声明为integer~~那么整个共用空间的属性就被定义为无害的integer型~~handle表就会忽视它~~永远不会进行追踪了~~
回复

使用道具 举报

发表于 2009-5-3 23:25:33 | 显示全部楼层
然后如果你很会动脑的话~~大概会有这样的疑问~~

如果我用这种形式
local udg_location= Location(0,0)
lcoal udg_i

也就是说在整个共用空间被重定义为无害的integer之前~~我先将其指向一个handle表位~~那么其结果会不会增加变量连接数?~~首先我得说这个想法很好但是毫无意义~~因为事实上Union Bug是不可能这样写的~~毕竟这种写法就意味着当udg_i被声明的时候~~整个共用空间的值已经成为udg_i的初值~~原有的值就消失了~~在Union Bug中~~最后一个变量被声明之前的赋值行为是没什么实际意义的~~

另外至于如果我硬要问说这个究竟会不会增加变量连接数?~~那么其实你可以自己分析下的~~首先当local udg_location= Location(0,0)执行的时候~~连接数其实是确确实实增加了的~~但是同时~~当下一条语句执行的时候~~两个变化发生了~~


第一个:由于共用空间有了新的初值~~那么显然就不再指向 Location(0,0)对应的表位~~于是该表位变量连接数被清空~~一旦你destroy了那个location~~这个表位就可以复用了~~

第二个:随着udg_i被声明~~共用空间的性质发生改变~~于是该共用空间的新值(不管是什么,就算udg_i的初值不为空)~~他也不会对handle表产生任何影响~~

因此就算是这种无聊的情况~~变量连接数造成的泄露还是照样被避免了~~
回复

使用道具 举报

发表于 2009-5-4 09:51:32 | 显示全部楼层
谢谢头目了
不过能不能使用J找出一个Handel的真正内存地址呢?
比如handle表中的1892323这个元素对应的东西(如单位)的物理地址
如果能的话
那么如果使用那么J的漏洞
我们就能修改一些原本没有对应函数的东西了
比如单位的模型……
如果修改的是一些没有检查意义的东西
比如模型,那么这样又能否达到同一个单位对应不同玩家是不同的模型呢?
以上是瞎想的……
回复

使用道具 举报

发表于 2009-5-4 09:54:50 | 显示全部楼层
这个自然是可行的~~不过得需要那个jass虚拟机漏洞而已~~

毕竟handle表它本身需要保存在内存里~~你既然能读取内存自然也能查询handle表然后得到实际内存地址了~~

不同模型也是可行的~~
回复

使用道具 举报

发表于 2009-5-4 12:46:58 | 显示全部楼层
也就是说unionBug的原理是不会覆盖最后一个声明的和全局类型不同的变量?还是别的什么东西?
回复

使用道具 举报

 楼主| 发表于 2009-5-4 13:22:24 | 显示全部楼层
....ls理解错了..
unionbug后 几个变量都指向同1个数据
而最后声明的变量 定义数据的类别
赋值任何1个变量 也就是改变了数据 别的变量读取时也自然改变了.

最后定义为handle
赋值负的 就出错 (本文讲的这个)


一句题外话~~话说发现LS的头像某个版本是X~~
因为某2个图片被我删了
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-3-28 21:17 , Processed in 0.316639 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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