07年做网站,关键词歌曲免费听,餐饮品牌全案策划公司,南昌商城网站建设公司Lua 绕过元表#xff0c;直接访问 table 的字段。
绕过元表
rawset(table, index, value)#xff0c;在不触发元方法的情况下#xff0c;设置 table[index] 的值为 value。
rawget(table, index)#xff0c;在不触发元方法的情况下#xff0c;获取 table[index] 的值。…Lua 绕过元表直接访问 table 的字段。
绕过元表
rawset(table, index, value)在不触发元方法的情况下设置 table[index] 的值为 value。
rawget(table, index)在不触发元方法的情况下获取 table[index] 的值。
现有一个 hero 表设置了元表和元方法。
local hero {level 1,exp 0
}local mt {__index function (table, key)print(trigger __index)end,__newindex function (table, key, value)print(trigger __newindex)end
}
setmetatable(hero, mt)如果去访问一个不存在的 key则会进入元表的元方法。
因为 __newindex 被赋值为一个函数只有打印没有把值存到 table 里所以 hero 里还是没有 star 字段。
hero.star 5
print(hero.star)-- trigger __newindex
-- trigger __index
-- nil现在使用 rawset 为 hero 添加一个新字段 star再使用 rawget 从 hero 中获取 star 字段。
可以发现没有触发元方法的打印hero 表中也添加了 star 字段。
rawset(hero, star, 5)
local star rawget(hero, star)
print(star)-- 5防止死循环
修改一下元方法在 __index 中返回 table[key] 的值在 __newindex 中设置 table[key] 为 value。
local hero {level 1,exp 0
}local mt {__index function (table, key)print(trigger __index)return table[key]end,__newindex function (table, key, value)print(trigger __newindex)table[key] valueend
}
setmetatable(hero, mt)看上去似乎没有什么问题但是如果触发了这两个元方法它们内部的逻辑也就是 table[key]又会触发元方法进入死循环最后栈溢出。
hero.star 5-- trigger __newindex
-- trigger __newindex
-- trigger __newindex
-- ...
-- C stack overflowprint(hero.star)-- trigger __index
-- trigger __index
-- trigger __index
-- ...
-- C stack overflow要防止这种死循环可以利用 rawset 和 rawget避免再次触发元方法。
local hero {level 1,exp 0
}local mt {__index function (table, key)print(trigger __index)return rawget(table, key)end,__newindex function (table, key, value)print(trigger __newindex)rawset(table, key, value)end
}
setmetatable(hero, mt)再次访问 star 字段就不会栈溢出了。
hero.star 5
-- trigger __newindexprint(hero.star)
-- 5