c++ - 我的 Lua 对象被收集了吗?

标签 c++ memory-leaks lua

警告:

我现在确信问题出在 luatraverse 脚本 explained here只是没有像宣传的那样工作,也没有找到对一个对象的所有引用。在我的示例中,我找到了对象被引用的位置,从而阻止了它的收集,但脚本没有报告这一点。

因此,这道题的基本前提是有些瑕疵的。

背景:

我正在努力增强游戏中的脚本引擎 Bitfighter .我不相信内存被正确释放。所以我以下面的脚本形式构造了一个测试。

它打印 3 列用户数据。第 1 列是一个用户数据,我预计不会在其他任何地方使用,因此应该被 collectgarbage 函数销毁。第 2 列和第 3 列是我认为不应该收集的对象,因为我正在处理它们。

问题:

第 1 列中的用户数据永远不会变化,因此我怀疑它没有被收集(第 2 列和第 3 列的行为符合预期)。为了进一步说明情况,我使用了 this problem 中提到的 luatraverse 脚本。 ,这似乎证实了只有一个对 obj100 的引用,即存储在 obj100 本身中的引用。我尝试在运行 countreferences (local x = obj100) 之前添加一个赋值,并且正如预期的那样,countreferences 报告对象被引用了两次。

问题:

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

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

代码:

 -- 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 

输出:

 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 ...

最佳答案

我不了解 Bitfighter,但我认为您在这里测量的是错误的东西:

这一行将创建一个新的 Lua userdata 对象,基本上指向真正的 C++(?)对象:

local obj100 = levelgen:findObjectById(100)

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

print(ltraverse.countreferences(obj100))

这将始终为 1,因为您刚刚创建了该对象并引用了它。

引用/Lua 对象很可能已被收集,您不会看到它。实际的用户数据(指针)始终相同,因为您请求的是相同的对象 ID。因此,该值不得更改,除非相关数据被其他代码移动/重新分配。

但最后,我想说这真的取决于 levelgen:findObjectById() 返回的内容。如果您尝试以下行会发生什么?

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

关于c++ - 我的 Lua 对象被收集了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14531901/

相关文章:

c# - 具有回调的委托(delegate)的内存泄漏

lua - 如何从lua中的字符串中删除点

c++ - 从全局对象的构造函数调用时的 std::atexit 排序

c++ - 如何将 C++ Wii devkitpro 连接到互联网?

c++ - 将批处理脚本作为 Windows 服务运行

PowerShell内存泄漏误解

c++ - GCC 错误,当使用 "linux"尖括号通过宏包含 header 时,路径中的 "1"字符串替换为 "<>"

Android AsyncTask 内存泄漏

string - 在 Lua 中嵌套括号有什么意义?

c++ - 使用Lua创建HTML GUI(HTML渲染)