是我的Lua对象被收集? [英] Is my Lua object being collected?

查看:126
本文介绍了是我的Lua对象被收集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

警告:



我现在相信问题是luatraverse脚本这里解释只是不工作的广告,并没有找到对一个对象的所有引用。在我的例子中,我发现对象被引用,从而阻止它的收集,但是没有报告脚本。



因此,这个问题的基本前提



我正在努力改进脚本引擎在游戏中 Bitfighter 。我不相信内存正在释放。所以我构建了一个测试,以下面的脚本的形式。



它输出3列userdatas。列1是一个userdata,我希望在别的地方使用,因此应该被collectgarbage函数销毁。列2和3是我不相信应该收集的对象,因为我在他们上保持一个句柄。



问题:



第1列中的userdata从不变,怀疑它未被收集(第2和3栏的行为与预期的相同)。为了进一步澄清情况,我使用此问题中提及的luatraverse脚本,这似乎确认了只有一个对obj100的引用,这是存储在obj100本身。我试图在运行countreferences(local x = obj100)之前添加一个赋值,并且如预期的那样,countreferences报告被引用两次的对象。





1)我正确地解释这个输出,是obj100真的没有收集吗?或者是否可能一次又一次地重复使用相同的内存地址?



2)有没有比luatraverse脚本更好的方法来查看引用特定Lua对象的内容?



代码:

   - 每2秒钟找到两个ids 100和200的对象,并打印它们的addrs 
- 不会为对象100保留引用,因此其用户数据可能随时间改变
- 对象200由objHolder保存,因此其userdata应保持不变

- Obj200应该随时间保持恒定; obj100可以改变。
- objHolder应该是常量,显然

local ltraverse = require(luatraverse)


函数printIds()
local obj100 = levelgen:findObjectById(100)
local obj200 = levelgen:findObjectById(200)
print(Obj 100:.. tostring(obj100)..Obj 200:..
tostring(obj200)..Held:.. tostring(objHolder))


print(ltraverse.countreferences(obj100))

obj100 = nil
obj200 = nil

collectgarbage()
end

函数main()
- levelgen:findObjectById是一个本地游戏命令
- 为对象创建一个userdata
local obj100 = levelgen:findObjectById(100)
objHolder = levelgen:findObjectById(200) - 不是本地,全局
$ b b assert(obj100)
assert(objHolder)

print(Column 1 can vary; 2 and 3 should be constant)
print(====== ===================================)

print (Obj 100:.. tostring(obj100)..Obj 200:..
tostring(objHolder)..Held:.. tostring(objHolder))

obj100 = nil

- 每2秒运行一次函数
定时器:scheduleRepeating(printIds,2000)
end

输出

  1可以变化; 2和3应该是常数
========================================== =====
Obj 100:userdata:02FC9700 Obj 200:userdata:02FAD280 Held:userdata:02FAD280

Obj 100:userdata:02FC9700 Obj 200:userdata:02FAD280持有:userdata: 02FAD280
1
Obj 100:userdata:02FC9700 Obj 200:userdata:02FAD280 Held:userdata:02FAD280
1
Obj 100:userdata:02FC9700 Obj 200:userdata:02FAD280持有人: userdata:02FAD280
1
Obj 100:userdata:02FC9700 Obj 200:userdata:02FAD280 Held:userdata:02FAD280
1
Obj 100:userdata:02FC9700 Obj 200:userdata:02FAD280 Held:userdata:02FAD280
1
... and onward to infinity ...




这行会创建一个新的Lua用户数据对象基本上指向真正的C ++(?)对象:

  local obj100 = levelgen:findObjectById(100)

稍后在下面一行将打印引用Lua指向该用户数据的引用数( obj100 ,而不是实际数据):

  print(ltraverse.countreferences(obj100)) 

这将总是1,因为你刚刚创建了一个引用它的对象。



引用/ Lua对象最有可能被收集,你不会看到。实际的userdata(指针)总是相同的,因为你请求相同的对象ID。因此,这个值不能改变,除非相关的数据被一些其他代码移动/重新分配。



但最后,我会说这真的取决于什么 levelgen:findObjectById()返回。

  local temp 
local obj100 = temp = levelgen:findObjectById(100)


The warning:

I am now convinced that the problem is that the luatraverse script explained here just does not work as advertised, and does not find all the references to an object. In my example, I found where the object was being referenced, thus preventing its collection, but that was not reported by the script.

Therefore, the basic premise of this question is somewhat flawed.

The backgound:

I am working on enhancing the scripting engine in the game Bitfighter. I am not convinced that memory is being released properly. So I constructed a test, in the form of the script below.

It prints 3 columns of userdatas. Column 1 is a userdata I expect to be used nowhere else, and should therefore be destroyed by the collectgarbage function. Columns 2 and 3 are objects I do not believe should be collected, because I am keeping a handle on them.

The problem:

The userdata in column 1 never varies, so I suspect it is not being collected (cols. 2 and 3 behave as expected). To further clarify the situation, I am using the luatraverse script mentioned in this problem, which seems to confirm that there is only one reference to obj100, which is that stored in obj100 itself. I tried adding an assignment just before running countreferences (local x = obj100), and, as expected, countreferences reported the object being referenced twice.

The questions:

1) Am I interpreting this output correctly, and is obj100 really never collected? Or is it possible that the same memory addresses is being reused over and over?

2) Is there a better way than the luatraverse script to see what is referencing a particular Lua object?

The code:

 -- Every 2 seconds, find two objects with ids 100 and 200, and print their addrs
 -- No reference is kept for object 100, so its userdata might change over time
 -- Object 200 is held by objHolder, so its userdata should remain constant

 -- Obj200 should remain constant over time; obj100 can vary.  
 -- objHolder should be constant, obviously

 local ltraverse = require("luatraverse")


 function printIds()
    local obj100 = levelgen:findObjectById(100)
    local obj200 = levelgen:findObjectById(200)
    print("Obj 100:" .. tostring(obj100) .. " Obj 200:" .. 
           tostring(obj200) .. " Held:" .. tostring(objHolder))


    print(ltraverse.countreferences(obj100))

    obj100 = nil
    obj200 = nil

    collectgarbage()
 end

 function main()
    -- levelgen:findObjectById is a local game command that
    -- creates a userdata for an object
    local obj100 = levelgen:findObjectById(100)
    objHolder    = levelgen:findObjectById(200)     -- not local, global

    assert(obj100)
    assert(objHolder)

    print("Column 1 can vary; 2 and 3 should be constant")
    print("=============================================")

    print("Obj 100:" .. tostring(obj100) .. " Obj 200:" .. 
         tostring(objHolder) .. " Held:" .. tostring(objHolder))

    obj100 = nil

    -- Run a function every 2 seconds
    Timer:scheduleRepeating(printIds, 2000)
 end 

The output:

 Column 1 can vary; 2 and 3 should be constant
 =============================================
 Obj 100:userdata: 02FC9700 Obj 200:userdata: 02FAD280 Held:userdata: 02FAD280

 Obj 100:userdata: 02FC9700 Obj 200:userdata: 02FAD280 Held:userdata: 02FAD280
 1
 Obj 100:userdata: 02FC9700 Obj 200:userdata: 02FAD280 Held:userdata: 02FAD280
 1
 Obj 100:userdata: 02FC9700 Obj 200:userdata: 02FAD280 Held:userdata: 02FAD280
 1
 Obj 100:userdata: 02FC9700 Obj 200:userdata: 02FAD280 Held:userdata: 02FAD280
 1
 Obj 100:userdata: 02FC9700 Obj 200:userdata: 02FAD280 Held:userdata: 02FAD280
 1
 ... and onward to infinity ...

解决方案

I don't know Bitfighter, but I assume you're measuring wrong things here:

This line will create a new Lua userdata object essentially pointing to the real C++(?) object:

local obj100 = levelgen:findObjectById(100)

Later on the following line will print the number of references withing Lua pointing to that userdata (obj100, not the actual data):

print(ltraverse.countreferences(obj100))

This will always be 1, because you just created that object with one reference to it.

The reference/Lua object is most likely collected, you won't see that. The actual userdata (pointer) is always the same, because you're requesting the same object ID. Therefore this value must not change, unless the associated data is moved/reallocated by some other code.

But in the end, I'd say this really depends on what levelgen:findObjectById() returns. What happens if you try the following lines?

local temp
local obj100 = temp = levelgen:findObjectById(100)

这篇关于是我的Lua对象被收集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆