c++ - C & Lua 防止bad access or double free

标签 c++ 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.

无论如何我可以阻止这种情况发生吗?

最佳答案

问题与所有权有关。让我们来看看你的 Lua 脚本:

a = structaInit();
b = structbInit();

这将创建 Lua 现在 拥有 的 C 对象。 Lua 将决定何时释放这些对象的内存。

那么这个呢?

structbSetA( b, a ); -- This add ++a.reference

首先,structbSetA 应该是 b 的成员,通过一个元表(所以它变成了 b:setA(a)) .但更重要的是,谁拥有 a

Lua 可以。因为它必须拥有 A; Lua 不能完全放弃仍在 Lua 内存中的对象的所有权。这意味着你的内部引用计数最终是没有意义的;唯一重要的是 Lua 的。

如果您打算将a的值存储在b中,这样b就可以引用a,那么只要 b 还活着,那么您就需要通过 Lua 方法来创建这种关系。您不能只是将 C 指针指向 b 中的 a 并期望一切顺利。

最简单的方法是,对于您创建的每个对象,在 Lua 注册表中创建一个表,用于存储 Lua 对象的任何引用。当一个对象被销毁时,您进入 Lua 注册表并从中删除该表,从而导致任何引用的 Lua 对象被销毁。显然,当以后调用 structbSetA 修改此值时,您将需要更改它。


另外,你为什么要把它暴露给 Lua:

a.reference = 0;

那是一个糟糕的 API。 Lua 代码应该永远 必须处理引用计数。你也不应该向 Lua 公开一个显式的“释放”方法,除非你需要 Lua 在使用完某些资源后立即释放它。这应该只有对于操作系统类型的资源(如 FILE 句柄等)是必需的。对于常规对象,让垃圾收集器完成它的工作。

不要将 C 语言暴露给 Lua 代码。让 Lua 代码看起来像 Lua 代码。

关于c++ - C & Lua 防止bad access or double free,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6658135/

相关文章:

c++ - 为什么 C 中字 rune 字的大小与 C++ 中的不同

c - 给定基本 block 中的指令位置,如何找到该基本 block ?

c - 我读过 The C Programming Language 我从这里去哪里?

C++ 在模板中重载 operator=

c++ - 链接器可以报告未使用的成员函数吗? (C++)(海合会)

c++ - 从 boost::shared_ptr 到 std::shared_ptr 的转换?

lua - 如何使用 Mod 键(Ctrl、Alt、Shift 等)在 Neovim 中编写 Lua 命令

c++ - "Template argument for template template parameter must be a class template or type alias template"

lua - 为什么 4 的倍数会导致 table.insert() 困惑?

lua - 如何在 Lua 中结束循环协程?