Lua元表对象无法从内存中清除?

我使用了一个专有的平台,在屏幕上实时报告内存使用情况。我决定使用我在http://lua-users.org/wiki/SimpleLuaClasses找到的Class.lua。

然而,我注意到使用一个简单的Account类创建的对象在清除内存时存在问题。具体来说,我开始使用146k的内存,创建1000个只包含一个整数实例变量的类对象,并将每个对象存储到一个表中。现在使用的内存为300k。

然后我退出,迭代表格并将表中的每个元素设置为nil。但不会回收146k,通常在此之后我会使用210k或类似的内存。如果在同一会话中再次运行加载顺序,则不会超过300k,因此这不是内存泄漏。

我尝试在表中创建1000个整数并将其设置为nil,这确实使我回收了146k。

此外,我尝试了一个更简单的类文件(Account2.lua),它不依赖于Class.lua。这仍会导致内存碎片,但不像使用Class.lua那样严重。

有人能解释这是怎么回事吗?我如何清除这些对象并恢复内存?

这里是代码

--------Class.lua------


-- class.lua
-- 兼容Lua 5.1(而不是5.0)。
--http://lua-users.org/wiki/SimpleLuaClasses。
function class(base,ctor)
  local c = {}       --一个新的类实例
  if not ctor and type(base) == 'function' then
      ctor = base
      base = nil
  elseif type(base) == 'table' then
   --我们的新类是基类的浅层副本!
      for i,v in pairs(base) do
          c[i] = v
      end
      c._base = base
  end
  --该类将是其所有对象的元表,
  --并且它们将在其中查找它们的方法。
  c.__index = c

  --暴露可以通过()调用的构造函数
  local mt = {}
  mt.__call = function(class_tbl,...)
    local obj = {}
    setmetatable(obj,c)
    if ctor then
       ctor(obj,...)
    else
    --确保基类的任何内容都已初始化!
       if base and base.init then
         base.init(obj,...)
       end
    end
    return obj
  end
  c.init = ctor
  c.instanceOf = function(self,klass)
      local m = getmetatable(self)
      while m do
         if m == klass then return true end
         m = m._base
      end
      return false
    end
  setmetatable(c,mt)
  return c
end

--------Account.lua------


--导入Class模板
require 'class'
local classname = "Account"
    --声明类构造函数
    Account = class(function(acc,balance)
    --在此处声明实例变量。
         if(balance ~= nil)then
                     acc.balance = balance
                    else
                     --默认值
                     acc.balance = 2097
                    end
                    acc.classname = classname
                 end)

--------Account2.lua------


local account2 = {}

account2.classname  = "未命名的"
account2.balance  = 2097

-----------构造函数1
do
 local metatable = {
  __index = account2;
 }

 function Account2()
  return setmetatable({}, metatable);
 end
end

--------Main.lua------


require 'Account'
require 'Account2'

MAX_OBJ    = 5000;
test_value = 1000;
Obj_Table = {};
MODE_ACC0 = 0 --整数
MODE_ACC1 = 1 --账户
MODE_ACC2 = 2 --Account2
TEST_MODE = MODE_ACC0;

Lua_mem = 0;

function Load()
 for i=1, MAX_OBJ do
    if(TEST_MODE == MODE_ACC0 )then
        table.insert(Obj_Table, test_value);

    elseif(TEST_MODE == MODE_ACC1 )then
         table.insert(Obj_Table, Account(test_value)); --Account.lua

    elseif(TEST_MODE == MODE_ACC2 )then
         table.insert(Obj_Table, Account2()); --Account2.lua
        Obj_Table[i].balance = test_value;
    end
 end
end

function Purge()
    --元表清除
    if(TEST_MODE ~= MODE_ACC0)then
      --清除阶段0:
      print("将每个元素的元表设置为nil")
      for i=1, MAX_OBJ do
        setmetatable(Obj_Table[i], nil);
      end
    end

    --清除阶段1:
    print("将表元素设置为nil")
    for i=1, MAX_OBJ do
      Obj_Table[i] = nil;
    end

    --清除阶段2:
    print("开始表删除...");
    for i=1, MAX_OBJ do

原文链接 https://stackoverflow.com/questions/2733406

点赞
stackoverflow用户1491
stackoverflow用户1491

你需要强制垃圾收集器回收内存(参见collectgarbage(“collect”))。

2010-04-29 13:49:45
stackoverflow用户1797155
stackoverflow用户1797155

Main.lua:


    --purge stage 0:
    print("将每个元素的元表设置为nil")
    for i=1, MAX_OBJ do
        setmetatable(Obj_Table[i], nil);
    end

根据Lua的文档,你不能通过将元表设置为nil来重置一个表的元表。这只会等同于getmetatable()函数。因此,对象仍然保持连接。

2012-11-03 21:08:02
stackoverflow用户936986
stackoverflow用户936986

大多数动态语言实际上不会将内存释放回系统,而是将其保留以备将来分配。在 Lua 报告内存减少之后尝试创建一些对象 - Lua 应该使用它自己保留的这些已释放的内存,这样平台内存消耗就不会增加。

2012-11-03 22:10:44