C和Lua防止错误访问或双重释放。
我成功地将Lua集成到我的C应用程序中,为用户提供了脚本访问权限。现在我的问题是:我该如何防止双重释放或坏访问违规?
我已经为每个结构实现了Init
和Free
函数,例如:
structaInit
structaFree
我还跟踪每次一个结构体指针链接到另一个指针,递增所有结构体中存在的引用计数。
然而,用户在Lua中总是可以做出这样的操作:
a = structaInit();
b = structbInit();
structbSetA( b, a ); -- This add ++a.reference
a.reference = 0;
a = structaFree( a ); -- If a->reference == 0 then I free
-- Then struct b->a is still a valid pointer but that have been free.
有没有任何方法可以防止这种情况发生?
原文链接 https://stackoverflow.com/questions/6658135
这个问题与所有权有关。让我们来看看你的 Lua 脚本:
a = structaInit();
b = structbInit();
这将创建 C 对象,现在 Lua 拥有这些对象。Lua 将决定何时释放这些对象的内存。
那么下面这个怎么办?
structbSetA( b, a ); -- 这个操作会增加 ++a.reference
首先, structbSetA
应该是 b
的成员,通过元表 (使其成为 b:setA(a)
)。但更重要的是,谁拥有 a
?
是 Lua。因为必须拥有 A; 只要一个对象仍然在 Lua 内存中,Lua 就不能完全放弃对象的所有权。这意味着你的内部引用计数最终是没有意义的;唯一重要的是 Lua 的引用计数。
如果您打算将 a
的值存储在 b
中,使 b
可以在 b
仍然存在时引用 a
,则需要通过 Lua 方法创建这种关系。您不能只是将 a
的 C 指针粘贴到 b
中,然后期望一切顺利。
最简单的方法是为您创建的每个对象在 Lua 注册表中创建一个表,用于存储任何引用的 Lua 对象的 Lua 对象。当对象被销毁时,您可以进入 Lua 注册表并将此表从中删除,因此导致任何引用的 Lua 对象的销毁。显然,您需要在后续对 structbSetA
的调用中修改此值。
此外,你为什么会向 Lua 公开这个:
a.reference = 0;
这是一个可怕的 API。Lua 代码永远不应该处理引用计数。您还永远不应该向 Lua 公开明确的 “释放” 方法,除非您需要 Lua 在使用资源后立即释放某些资源。这应该只对类似 FILE 句柄等的 OS 类资源是必要的。对于普通对象,请让垃圾收集器完成其工作。
不要向 Lua 代码公开 C 的思想。让 Lua 代码看起来像 Lua 代码。
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
在这种情况下,它归结为编程实践,你不会真的想要防止它,实际上你想让它发生错误,因为这样使用你的脚本的人们就知道他们正在做错事情(就像在 obj-c 中当你过度释放时会崩溃一样)。如果你不想让这种情况发生,你可能需要跟踪指向结构体在堆上的所有活动指针并将它们放在一个链表或某个结构中,但我认为这并不值得。