找回密码
 点一下
查看: 1371|回复: 16

关于return bug 的疑问,望高手解答。

[复制链接]
发表于 2008-2-22 22:48:27 | 显示全部楼层 |阅读模式
问一下return bug存不存在这样一个漏洞:

  function H2I takes handle h returns integer
                return h
                return 0
    endfunction

看上去,上面那个函数很巧妙的将handle转换城了integer。但是,handle是什么?其实handle是一个指针,他指向的是一个可能比较复杂数据结构,把他直接转化为integer,其实是获得指针的值。

那么,你看~~,如果handle是一个local型的数据,它的生命周期是局部的,如果把它转换为integer并且保存了,在其他函数中使用时,也许handle已经过期了。那么会出现什么情况????那么,就会访问并不存在的数据,如果要赋值的话,情况可能会更严重,可能会把不该覆盖的数据覆盖了。也许会导致WarIII崩溃。。。。。。

举个例子:
  function some function................
            local handle a
            //...........some code ...............
            save to gamecache( H2I( a ))
  endfunction

  function some function...................
            local handle a = I2H( LoadFromGameCache( .... ))
            //some codes ............
            a = ..........//a 还有效么???
  endfunction

不知道以上分析有没有道理???请高手赐教
 楼主| 发表于 2008-2-22 23:00:52 | 显示全部楼层
自己顶下。不然要沉了。期待高手回答。
回复

使用道具 举报

发表于 2008-2-22 23:14:04 | 显示全部楼层
感觉不会吧
觉得GameCache是保存了那个handle的信息,不是指针吧
我也是新手,一起学习,期待高手回答。
回复

使用道具 举报

发表于 2008-2-22 23:17:37 | 显示全部楼层
找到个证据,局部变量可以用 GameCache 传递
function Trig_BaoFengXue_______u_Actions takes nothing returns nothing
    local rect rtA = RectFromCenterSizeBJ(GetSpellTargetLoc(), 500.00, 500.00)
    call StoreInteger(GameCache(), I2S(H2I(tm)), "rect", H2I(rtA))
    ...
endfunction

function BaoFengXueTeXiao takes nothing returns nothing
    local rect rtA = I2RC(GetStoredInteger(GameCache(), I2S(H2I(tm)), "rect"))
    ...
endfunction
这个是zhuzeitou大人上午做的那个大暴风雪的演示中的东西
具体原因不清除
回复

使用道具 举报

发表于 2008-2-23 00:03:57 | 显示全部楼层
GameCache存储方式 相当于全局变量
在程序的各处都可以访问
而且 只要你不重新设定它的值 是不会改变的

LZ你举的例子只是想当然的
回复

使用道具 举报

发表于 2008-2-23 00:55:40 | 显示全部楼层
按照C语言,指针本身就是一个整型变量,保存的是地址。
JASS里面的句柄应该应该也是象指针这样吧,那么H2I函数得到的返回值就是一个地址,只要申请的内存没有释放,任何时候都可以通过地址访问得到指针所指向的值。所以象点、单位组等都需要释放内存,否则就会引起内存泄露。
局部变量的指针过期了,只是用来保存地址的那个整型变量过期了而已,和他所指向的值无关。
回复

使用道具 举报

发表于 2008-2-23 00:58:58 | 显示全部楼层
handle指向目标是可能更改或者消失的~~

不过这跟他的生命周期倒毫无关系~~用局部变量指向的对象不会因为指向它的局部变量到期而消失~~



而一个handle如果指向一个对象~~而这个对象已被destroy掉的话~~就会指向不存在的对象~~甚至~~如果这种对象的handle是可回收的(也就是说删掉一个对象后新建对象会占用被删掉对象的handle值的话)~~那么甚至可能指向一个完全不同的对象~~

并非所有的对象handle都是可回收的~~也并非所有对象都是可被销毁的~~
回复

使用道具 举报

 楼主| 发表于 2008-2-23 04:34:04 | 显示全部楼层
也就是说,如果

local handle a;
不仅同时定义了一个局部变量a,还在“堆”中同时申请了内存???

按照C或者C++,局部变量一旦过期,其内存空间也会被释放。
JASS不是这样的么???

a = null
这样就能把内存释放么???

按照C或者C++,这样只是把指针赋值为空了。不会释放内存的。

如果说handle需要显示的创建,那么rect呢???rect是不需要显示创建的。
比如:handle a = CreateXXX(....);
这样,必须有Destory(。。。)才会释放内存。

但是如果要想保存rect数据呢?rect 有CreateRect么??
回复

使用道具 举报

 楼主| 发表于 2008-2-23 04:38:40 | 显示全部楼层
引用第4楼zj54891于2008-02-23 00:03发表的  :
GameCache存储方式 相当于全局变量
在程序的各处都可以访问
而且 只要你不重新设定它的值 是不会改变的

LZ你举的例子只是想当然的
.......

GameCache当然相当于全局变量。这点大家都清除。我问的问题是,局部变量如果过期,其保存在GameCache中的指针数据,会不会变成无效的。
就像C里面:

somefunciton()
{
    int a;   //局部变量
        save ( & a); //保存局部变量的指针
}
otherfunction()
{
     int * a;
     a = load ();
}

上面的代码编译时不会有任何问题,但是,它时错误的。
回复

使用道具 举报

发表于 2008-2-23 05:40:55 | 显示全部楼层
楼主的例子是存在的,在一个“xx已知bug”的帖子里有过描述;
rect和unit在这上面有着相同的本质有DestroyUnit 同时也有RemoveRect ;创造单位的函数是CreateUnit(player,id,x,y,facing)创造区域的函数是Rect(x1,x2,y1,y2)
释放句柄的方式是set null,但原理上似乎又不是一定会释放,这个操作是将句柄的引用数减1,当引用数降到0时才能达成释放的条件。不过这方面我也是照搬别人讲的,自己也并非很清楚啦,要等专业人士来解释
回复

使用道具 举报

发表于 2008-2-23 08:49:16 | 显示全部楼层
引用第7楼sdhexu于2008-02-23 04:34发表的  :
也就是说,如果

local handle a;
不仅同时定义了一个局部变量a,还在“堆”中同时申请了内存???

.......

其实并不用想得太麻烦~~毕竟handle和指针其实有很大区别~~说到底只是一个游戏内对象的编号而已~~也不代表什么地址意义~~

你可以单纯地把所有handle类型的变量想象为一个简单的整型变量~~(当然实际上稍微复杂点)

只有用createXXX后它才会创建对应的对象~~

rect当然有创建函数~~就是rect()~~


而且~~并非所有类型的handle变量会指向某种对象~~某些只是一串单纯的数字而已~~
回复

使用道具 举报

发表于 2008-2-23 11:33:09 | 显示全部楼层
引用第7楼sdhexu于2008-02-23 04:34发表的  :
也就是说,如果

local handle a;
不仅同时定义了一个局部变量a,还在“堆”中同时申请了内存???

按照C或者C++,局部变量一旦过期,其内存空间也会被释放。
JASS不是这样的么???
local handle a;只定义局部变量,然后后面的CreateTimer()之类的才申请内存。
我记得C++里面用new分配的内存delete不会释放的
回复

使用道具 举报

 楼主| 发表于 2008-2-23 13:14:27 | 显示全部楼层

[quote]引用9楼的描述:

引用9楼的描述:
rect和unit在这上面有着相同的本质有DestroyUnit 同时也有RemoveRect ;创造单位的函数是CreateUnit(player,id,x,y,facing)创造区域的函数是Rect(x1,x2,y1,y2)释放句柄的方式是set null,但原理上似乎又不是一定会释放,这个操作是将句柄的引用数减1,当引用数降到0时才能达成释放的条件.

那么,您是说,要定义个rect并使用它,应该是这样:
local rect rt = CreateRect(......)

//some use rt code.....

RemoveRect(...)

而不是这样??
rect rt

//some use rt code.....
回复

使用道具 举报

 楼主| 发表于 2008-2-23 13:22:27 | 显示全部楼层
引用第10楼Renee于2008-02-23 08:49发表的  :


其实并不用想得太麻烦~~毕竟handle和指针其实有很大区别~~说到底只是一个游戏内对象的编号而已~~也不代表什么地址意义~~

你可以单纯地把所有handle类型的变量想象为一个简单的整型变量~~(当然实际上稍微复杂点)
.......

句柄是什么????
句柄实际上就是一个数据结构,或者一个类的实例,或者说一个对象的与地址相关的DWORD值。可能是这个对象的首地址,也可能能某个对象的加载地址,反正通过这个DWORD值,可以引用该对象。因此,它和指针是非常相似的。
比如Windows进程句柄,事实上,在数值上就是Windows加载该进程的模块的首地址。
回复

使用道具 举报

发表于 2008-2-23 13:26:59 | 显示全部楼层
handle不是指针,H2I返回值不过是一个标号,是handle表中数据的一个编号,CreateRect(......)会在HANDLE表中申请一个空间,这个空间的编号是handle的内容,而该空间的内容是实际地址指针和变量连接数,如果你使用的是局部变量的话,local rect rt = CreateRect(......)将直接使该编号的handle表的变量连接数加1,rt是回自动回收的,但是指向的handle表内容不会,因此这个handle值始终是有效的,他始终指向一个固定不变的地址,即使这个空间的内容改了你也不会找不到东西,但却有可能因为找到的东西不正确而崩溃.

以下是handle表的结构,自己理解吧,这些都是我实际反汇编总结的不会有错

typedef struct
{
    int VarCount;        //指向该编号的变量数
    int HandleAddress;    //该编号所对应HANDLE的实际地址
    int UnKnow;        //还没看出来,貌似一直是0 - -...
}HandleTableElement;
回复

使用道具 举报

发表于 2008-2-23 13:32:28 | 显示全部楼层
另外句柄的可以定义成任何东西,即使在C里你完全可以把数组下标当作句柄,WINAPI的句柄虽然往往是指针,但这是WAR3不是WINAPI,看看H2I的返回值就知道,如果他是指针则将指向WAR3加载地址以上的空间,着怎么可能呢?
回复

使用道具 举报

发表于 2008-2-23 13:34:16 | 显示全部楼层
引用第13楼sdhexu于2008-02-23 13:22发表的  :


句柄是什么????
句柄实际上就是一个数据结构,或者一个类的实例,或者说一个对象的与地址相关的DWORD值。可能是这个对象的首地址,也可能能某个对象的加载地址,反正通过这个DWORD值,可以引用该对象。因此,它和指针是非常相似的。
比如Windows进程句柄,事实上,在数值上就是Windows加载该进程的模块的首地址。

都说了他不是什么东西了~~叫你当integer理解嘛~~哪来什么结构~~

你说那些句柄概念是没错~~不过那是其他编程语言里的概念~~别硬套到jass~~
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-23 16:50 , Processed in 0.032399 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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