我成功地将Lua集成到了我的应用程序中,为用户提供了脚本访问权限.现在我的问题是:我如何防止双重免费或不良访问违规?
我已经为每个结构实现了Init和Free函数,例如:
structaInitstructaFree每次将struct指针链接到另一个时,我也会跟踪,增加我所有结构中的引用计数.
但是用户总是可以在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.
Run Code Online (Sandbox Code Playgroud)
无论如何我可以阻止这种情况发生吗?
Nic*_*las 10
问题与所有权有关.我们来看看你的Lua脚本:
a = structaInit();
b = structbInit();
Run Code Online (Sandbox Code Playgroud)
这会创建Lua现在拥有的 C对象.Lua将决定何时为这些对象释放内存.
那么这个怎么样?
structbSetA( b, a ); -- This add ++a.reference
Run Code Online (Sandbox Code Playgroud)
首先,structbSetA应该是一个成员b,通过metatable(所以它成为b:setA(a)).但更重要的是,谁拥有a?
Lua.因为它必须拥有A; Lua无法完全放弃仍在Lua内存中的对象的所有权.这意味着您的内部引用计数最终毫无意义; 唯一重要的是Lua's.
如果要存储的值a之内b,这样b可以参考a,只要b还活着,那么你就需要通过建立这种关系的Lua方法.你不能只是贴在C指针,指向a在b和期望一切顺利.
最简单的方法是,对于您创建的每个对象,在Lua注册表中创建一个表,该表存储Lua对象以用于它具有的任何引用.当一个对象被销毁时,你进入Lua注册表并从中删除该表,从而导致任何引用的Lua对象的销毁.显然,在以后的调用修改它时,您需要更改此值structbSetA.
另外,你为什么要把它暴露给Lua:
a.reference = 0;
Run Code Online (Sandbox Code Playgroud)
这是一个糟糕的API.Lua代码永远不必处理引用计数.你也不应该向Lua公开一个明确的"免费"方法,除非你需要Lua在完成使用后立即释放一些资源.这应该只适用于操作系统类型的资源,如FILE句柄等.对于常规对象,让垃圾收集器完成它的工作.
不要将C-isms暴露给Lua代码.让Lua代码看起来像Lua代码.