如何执行lua_pushstring并避免内存不足的setjmp异常。
有时候,在分配了一些需要在失败的情况下清理的资源之后,我希望在某些地方使用lua_pushstring。然而,正如文档所暗示的那样,lua_push*函数总是可能出现内存不足的异常。但是,该异常会立即退出我的C范围,不允许我清理任何我可能临时分配的资源,以防出现错误。
示例代码以说明情况:
void* blubb = malloc(20);
...在这里发生其他事情...
lua_pushstring(L, "test"); //如何安全地进行这个调用,以便我仍然可以关心 blubb?
...在这里有更多的事情可能发生...
free(blubb);
有没有一种方法可以事先检查是否会发生这样的异常,然后在安全清理自己的资源后避免推送并触发自己的错误?或者,我可以以某种方式简单地取消setjmp,然后在进行推动后检查一些“魔法变量”,以查看它是否实际上起作用或触发了一个错误?
我考虑过p调用我的自己的函数,但是即使只是将要通过p调用的堆栈上的函数推入堆栈,我也可能会遇到内存不足的情况,不是吗?
为了澄清问题,我专门为与自定义内存分配器结合使用而询问这个问题,这将防止Lua分配过多的内存,因此假定这不是整个系统已经耗尽内存的情况。
原文链接 https://stackoverflow.com/questions/10263585
除非您在创建 Lua 状态时已使用 Lua 注册了用户定义的内存处理程序,否则出现内存不足错误意味着您的整个应用程序已经耗尽了内存。通常情况下,从此状态恢复是不可能的。或者至少,在很多情况下不实际。可能取决于您的应用程序,但可能性不大。
简而言之,如果出现这种情况,你会有更重要的事情需要关注 ;)
唯一应影响您的那些是与应用程序外部相关的清理工作。如果您需要释放一些进程全局内存或设置一些状态,则需要清理工作。如果您正在进行进程间通信并且需要通过内存映射文件进行通信。或者类似的事情。
否则,最好只是杀死您的进程。
您可以将 Lua 构建为 C++ 库。这样做时,错误会变成实际的异常,您可以捕获它们或只使用 RAII 对象来处理它们。
如果您被困在 C 中...嗯,您没什么可做的。
我有一个特别感兴趣的自定义分配器,它将较早地分配内存,以避免 Lua 消耗太多内存。
那么你应该以另一种方式处理它。发出内存不足错误信号基本上意味着“我要让 Lua 立即终止”。
停止 Lua 占用内存的方法是定期检查 Lua 状态的内存,如果它使用过多,则进行垃圾回收。如果那并没有释放足够的内存,那么您应该手动终止 Lua 状态,但仅在安全的情况下才能这样操作。
我最近又开始使用 Lua 沙盒,现在我认为我之前接受的答案是一个坏主意。我仔细考虑了一下:
为什么周期性检查是不够的
如果你考虑到一个单独的巨大表格可以用一个 VM 指令吃掉你很多内存,关于这一点你只有在它发生之后才会知道,你只有在安全时才终止 Lua,这似乎是一个坏主意 - 在这种情况下,你的程序可能已经因此死掉,这时你确实有更大的问题,如果你及时停止了分配,完全可以避免这些问题。
由于 Lua 已经内置了很好的内存异常处理,因此我只想使用它,因为这允许我做最少的必要事情(防止脚本分配更多东西,同时可能允许其恢复),而不会破坏我的 C 代码。
因此,我目前的 Lua 沙盒内存限制计划是:
-使用定制的分配器,返回带有限制的 NULL。
-设计所有 C 函数以能够在无异常泄漏或其他故障的情况下处理此问题。
但如何安全地设计 C 函数?
如何做到这一点,因为 lua_pushstring 等函数总是可以在未知错误的情况下 setjmp,我不知道这是否会提前发生?(这是我的原始问题)
我认为我找到了一个可行的方法:
我添加了一个注册指针的功能,当我分配它们时进行注册,当我完成它们时进行注销。这意味着如果 Lua 突然将我从我的 C 代码中的 setjmp 中调出而没有让我有机会清理,我有一个全局列表,我需要清理这个混乱,等我重新掌控时。
那丑陋不?
是的,这很丑陋。但是,它很可能会起作用,并且与“周期性检查”不同,它实际上允许我拥有真正的硬限制,并且避免应用程序本身因为攻击太过激进而遇到麻烦。
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
lua_atpanic() 可能是你需要的解决方法之一,具体取决于你需要进行的清理类型。它不会抛出错误。
在你的具体例子中,你也可以创建
blubb
作为 userdata。然后当 Lua 离开栈时,它将自动释放。