C和Lua防止错误访问或双重释放。

我成功地将Lua集成到我的C应用程序中,为用户提供了脚本访问权限。现在我的问题是:我该如何防止双重释放或坏访问违规?

我已经为每个结构实现了InitFree函数,例如:

  • 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

点赞
stackoverflow用户392046
stackoverflow用户392046

在这种情况下,它归结为编程实践,你不会真的想要防止它,实际上你想让它发生错误,因为这样使用你的脚本的人们就知道他们正在做错事情(就像在 obj-c 中当你过度释放时会崩溃一样)。如果你不想让这种情况发生,你可能需要跟踪指向结构体在堆上的所有活动指针并将它们放在一个链表或某个结构中,但我认为这并不值得。

2011-07-12 00:06:25
stackoverflow用户734069
stackoverflow用户734069

这个问题与所有权有关。让我们来看看你的 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 代码。

2011-07-12 00:24:02