C&Lua防止不良访问或双重释放
C & Lua prevent bad access or double free
我成功地将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
仍然存在,b
就可以引用a
,那么您需要通过Lua方法创建这种关系。你不能只是把C指针指向b
中的a
,然后期望一切顺利。
最简单的方法是,对于您创建的每个对象,在Lua注册表中创建一个表,该表存储Lua对象所具有的任何引用。当对象被销毁时,您进入Lua注册表并从中删除该表,从而导致销毁任何引用的Lua对象。显然,当稍后调用structbSetA
修改该值时,您需要更改该值。
还有,为什么你要把这个暴露给Lua:
a.reference = 0;
这是一个糟糕的API。Lua代码不应该处理引用计数。您也不应该向Lua公开显式的"free"方法,除非您需要Lua在完成使用后立即释放某些资源。对于操作系统类型的资源,如文件句柄等,应该只需要。对于普通对象,让垃圾回收器完成它的工作。
不要将c语言暴露给Lua代码。让Lua代码看起来像Lua代码
在这种情况下,它归结为编程实践,你真的不想阻止它,你实际上想让它出错,因为使用你的脚本的人知道他们做错了什么(同样的方式在obj-c它崩溃当你过度释放)。如果你不想发生这种情况,你可能不得不跟踪堆上所有指向链表或其他结构体的活动指针,但我认为这是不值得的。
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 用于访问容器<T>数据成员的正确 API
- 释放错误后堆使用
- 我是否访问了已释放的内存,或者在这种情况下DrMemory报告不正确?
- 为什么在 C++ 执行删除操作后仍可以访问释放的动态分配的内存
- 内存泄漏,访问释放内存和双重免费之间有什么区别
- 在C++中,获取/释放原子访问和结合围栏的放松访问之间有什么有效的区别吗
- 当我通过删除临时节点来释放内存时,我会得到读取访问违规行为.但是只有当我返回错误语句时
- 在释放了所有作用域内指针之后仍然可访问内存
- 调试对释放内存的非法访问
- 在已释放的内存中访问
- 在 tesseract、c++ 中释放 char* 时访问冲突
- 获取/释放通过[]操作符访问的原子变量的语义
- 在释放模式下访问时矢量大小为0
- 释放模式下的访问违规
- 在初始化列表中创建单例对象会导致访问冲突(仅释放模式)
- C&Lua防止不良访问或双重释放
- 从您无法控制且无权访问的线程中释放 Python 导入锁