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

war3中string句柄系统

[复制链接]
发表于 2007-1-18 13:41:00 | 显示全部楼层 |阅读模式
在war3中除了handle类型外其实string也是一个句柄,不过它的句柄系统和handle句柄系统区分开了
[jass]
function S2HI takes string s return integer
return s
return 0
endfunction
function HI2S takes integer i return string
return i
return null
endfunction
[/jass]
所有在string其实都是一个从integer直接type出来的,而不是一个内存地址。war3能通过这个整数值得知strings所对应的字符串的内存地址。
string句柄系统维护了一个字符串的内存地址到string句柄的映射。

句柄系统用一个变长的string_handle_table来工作
string_handle_item需要存储下列信息。
unknow hash:这个是用来确定一个字符串的
char* StrAddr:这个就是实际字符串的指针

当jass中定义一个string时.如:
jass:: string s="ga.wowar.com"
先把"ga.wowar.com"存放在内存中.
war3:: char* str="ga.wowar.com";
然后计算Hash(str)在string_handle_table中根据hash寻找
如果有相同的那么直接给jass::s赋值为string_handle_item的索引
如果没有那么在string_handle_table末尾加上一个string_handle_item;
把string_handle_item.StrAddr设置为str,hash设置为Hash(str)。
返回该string_handle_item的索引

没时间了,要去考试了...
没想到大专的考试也这么难
回来继续...

从0到20的句柄是不能使用的,
除了空格外,其他的string的句柄值都是偶数。

经过测试:
所有的局部变量string在内存中占用的空间都不会被实际释放,而只是销毁其句柄变量string
当局部变量被销毁后,在没有发现string句柄这个特性之前,我们是不能访问到它们的。
但是现在,我们可以用HI2S来得到一个string.并且这个string能够正常工作,现在还没有得到写权限的方法。因为还没有办法直接把句柄值赋值给句柄变量。



这个特性可以使一个函数访问到另一个函数的局部string
也可以访问到玩家的聊天信息,因为聊天信息会跟新句柄表。
使用这个技术配合读档来载入游戏可以把关键数据隐藏到你的Jass脚本之外,放到存档当中去


如果你有什么装备系统,技能系统等等。可以把平衡性数据用这个技术隐藏一下。
这个技术仅仅用于炫耀,没有太大的用途

 楼主| 发表于 2007-1-18 16:22:48 | 显示全部楼层

句柄系统用于数据串行化

想到war3是怎么保存游戏的?
猜想:
被保存的数据:
负责运行jass脚本的栈区:所有的局部变量和线程
jass的全局变量:所有的全局变量
句柄表:句柄系统所需,保证jass中使用句柄系统的变量类型能正常工作
句柄指向的数据:这些数据是零散的,但是保存时会让它们紧凑的,每保存一个数据就修复一个句柄表中的指向。使它们指向文件中数据的位置。
读取纪录在载图完毕后不会马上进入游戏而是接着
恢复句柄表,然后根据句柄表从文件中把数据读到内存,每读出一个数据就修复句柄表中对数据的指针。
然后恢复jass全局变量,恢复jass的运行栈区
回复

使用道具 举报

发表于 2007-1-18 16:32:03 | 显示全部楼层
其实那2个函数偶很久以前就测试过呢...
句柄值也有奇数的...
继续测试中...
回复

使用道具 举报

 楼主| 发表于 2007-1-18 17:14:36 | 显示全部楼层
我什么时候把存档格式解出来就无敌鸟
回复

使用道具 举报

发表于 2007-1-18 17:35:36 | 显示全部楼层
刚做了个测试验证
[trigger]
Test
    Events
        Time - Every 0.10 seconds of game time
    Conditions
    Actions
        Custom script:   local integer ind=0
        Custom script:   local string s
        Custom script:   loop
        Custom script:   exitwhen ind==100
        Custom script:   set s="This is only a test"+I2S(ind+udg_i*100)
        Custom script:   set ind=ind+1
        Custom script:   endloop
        Custom script:   set udg_i=udg_i+1
        Custom script:   if udg_i==((udg_i/10)*10) then
        Custom script:   call BJDebugMsg(I2S(udg_i/10))
        Custom script:   endif
[/trigger]
一开始素每0.01s触发的,然后当开启触发后war3基本死掉,只剩下内存在涨...
经修改后测试,发现刚开始时没问题,内存占用一直稳定上涨,但当udg_i到400以后明显变慢,内存占用有上下浮动的现象产生,估计是因为war3的内存管理器在运作
总体上说,局部变量确实没有被释放,而且随着字符串数量增多,单位字符串的内存占用也会增多...
(udg_i到200时平均长度23,到1000时就变成料34...)
回复

使用道具 举报

 楼主| 发表于 2007-1-18 18:02:43 | 显示全部楼层
使用同样的字符串会得到同样的句柄
而且不会为重复的字符串分配内存
回复

使用道具 举报

发表于 2007-1-19 08:29:27 | 显示全部楼层
引用第4楼白银の式神2007-01-18 17:35发表的:
刚做了个测试验证
[trigger]
Test
    Events
        Time - Every 0.10 seconds of game time
.......



string对象是无法销毁的,貌似其他语言也一样吧。。。
回复

使用道具 举报

发表于 2007-1-19 08:43:58 | 显示全部楼层
变量是否被清除应该这样测试:
[jass]
function aa takes nothing returns nothing
local string s = "AAA"
endfunction

call TimerStart(CreateTimer(),0,true,function aa)[/jass]
回复

使用道具 举报

 楼主| 发表于 2007-1-19 12:11:25 | 显示全部楼层
LS的我没看懂,我是这样的。
[jass]function localvtest takes nothing returns integer
local string s="ga.wowar.com"
return s
return 0
endfunction
call Debug(HI2S(localvtest()))[/jass]

可以猜测code类型的变量应该也是一种句柄变量
回复

使用道具 举报

 楼主| 发表于 2007-1-19 12:13:55 | 显示全部楼层
引用第6楼Red_Wolf2007-01-19 08:29发表的:




string对象是无法销毁的,貌似其他语言也一样吧。。。
C++能销毁
gathx能销毁
高级语言基本上都支持销毁string
回复

使用道具 举报

发表于 2007-1-19 14:50:50 | 显示全部楼层
function localvtest takes nothing returns integer
local string s="ga.wowar.com"
return s
return 0
endfunction
call Debug(HI2S(localvtest()))

你这个看到的是string对象而不是变量,
变量在函数结束时就会被销毁,即使是需要set null的handle类变量也一样
需要set null并不是变量没被销毁而是它指向的那个位置未被腾出来
比如:
[jass]
local location p1 = Location(0,0)
local location p2 = Location(0,0)
call BJDebugMsg("P1:"+I2S(h2i(p1)))
call BJDebugMsg(("P2:"+I2S(h2i(p2)))
set p1 = p2
set p2 = null
[/jass]

以上代码未被释放的必定是原p1点
设L为点所在地址,则
set p1 = L1   ,L1的引用计数+1
set p2 = L2   ,L2的引用计数+1
set p1 = p2   ,L1的引用计数-1,L2的引用计数+1
set p2 = null ,L2的引用计数-1

函数运行完毕后L1引用计数为0,L2的引用计数为1,于是L1位置可以再次被使用,L2却将永远不会再被使用
这应该是jass设计上的失误,局部变量被销毁时,引用对象的引用计数并未被-1所导致的
回复

使用道具 举报

发表于 2007-1-19 14:55:33 | 显示全部楼层
string地址并没有奇偶之分
请注意:
I2S(S2HI("AA"))

AA是一个string,函数本身也是一个string
回复

使用道具 举报

发表于 2007-1-19 14:57:10 | 显示全部楼层
另如"AA"+"BB"+"CC"
会产生5个string

"AA"
"BB"
"AABB"
"CC"
"AABBCC"
回复

使用道具 举报

 楼主| 发表于 2007-1-19 15:00:19 | 显示全部楼层
不跟你争,句柄变量是存放句柄的,jass中的string就是句柄变量。
而war3是c++写的,其中的string是类。
我的代码是证明是jass::string被销毁但是war3::string不被销毁。
不必争论,大家都知道的事实,只是文字不好交流而已。
回复

使用道具 举报

发表于 2007-2-1 16:26:40 | 显示全部楼层
说起来~~这个东西有一个作用是可以获得地图名字等信息~~

比如地图名的Handle值总是3~~
回复

使用道具 举报

发表于 2007-2-1 16:29:17 | 显示全部楼层
一般来说可以得到地图名、地图介绍、地形设置、昼夜音效等等信息~~
回复

使用道具 举报

发表于 2007-2-1 16:33:20 | 显示全部楼层
貌似和java差不多
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-24 18:02 , Processed in 0.035538 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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