C++ C&;Lua防止错误访问或双重释放

C++ C&;Lua防止错误访问或双重释放,c++,c,lua,C++,C,Lua,我成功地将Lua集成到我的C my应用程序中,为用户提供了脚本访问权限。现在我的问题是:如何防止双重自由或错误访问违规 我已经为每个结构实现了Init和Free函数,例如: structaInit structaFree 每次一个结构指针链接到另一个结构指针时,我都会进行跟踪,增加所有结构中存在的引用计数 但是,用户在Lua中始终可以执行以下操作: a = structaInit(); b = structbInit(); structbSetA( b, a ); -- This add

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

我已经为每个结构实现了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.

无论如何,我能阻止这种情况发生吗?

在这种情况下,归结到编程实践中,你并不真的想阻止它,你实际上想让它出错,因为这样使用你的脚本的人知道他们做错了什么(在obj-c中,当你过度释放时,它会崩溃)。如果您不想发生这种情况,您可能必须跟踪堆上指向链接列表或某些结构的所有活动指针,但我认为这不值得。

问题与所有权有关。让我们看一下您的Lua脚本:

a = structaInit();
b = structbInit();
这将创建Lua现在拥有的C对象。Lua将决定何时释放这些对象的内存

那么这个呢

structbSetA( b, a ); -- This add ++a.reference
首先,
structbSetA
应该通过元表成为
b
的成员(因此它变成
b:setA(a)
)。但更重要的是,谁拥有
a

卢亚知道。因为它必须拥有一个;Lua无法完全放弃仍在Lua内存中的对象的所有权。这意味着您的内部引用计数最终毫无意义;唯一重要的是Lua的

如果要在
b
中存储
a
的值,以便
b
可以引用
a
,只要
b
仍处于活动状态,则需要通过Lua方法创建此关系。在
b
中,不能只将C指针指向
a
,然后期望一切顺利

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


还有,你为什么要把这个暴露给Lua:

a.reference = 0;
这是一个糟糕的API。Lua代码不应该处理引用计数。您也不应该向Lua公开显式的“free”方法,除非您需要Lua在使用完某个资源后立即释放它。这应该只对操作系统类型的资源(如文件句柄等)是必需的。对于常规对象,让垃圾收集器完成其工作


不要向Lua代码公开C-ISM。让Lua代码看起来像Lua代码。

你不能,你只能任由编写错误代码的人摆布,但这不是你的问题。你可以,但开销将是荒谬的:\n就像memcheck和kmemcheck函数一样。他们可以跟踪这一点,但性能会受到极大的影响。@Jeff:这段代码有什么不好的地方?如果一个暴露于Lua的对象能够存储另一个暴露于Lua的对象,那么Lua程序员应该合理地期望对该对象的引用不会消失。问题在于API。任何API都不应该直接向Lua公开引用计数。API也不应该明确要求Lua代码释放某些东西(除非它是类似于文件的东西,必须关闭它才能释放操作系统资源)特别是最后两句话。