Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Lua-重置脚本的状态而不重新设置脚本的权限_C_Performance_Lua_Reset - Fatal编程技术网

C Lua-重置脚本的状态而不重新设置脚本的权限

C Lua-重置脚本的状态而不重新设置脚本的权限,c,performance,lua,reset,C,Performance,Lua,Reset,我有一个运行Lua脚本的应用程序。每个Lua脚本可能会运行几次。有些脚本甚至可能在每次按键时运行 我希望在每次运行之间“重置”这些脚本。也就是说,如果用户设置了一个变量Foo,那么Foo在下次运行时不应该存在于脚本中,直到用户再次定义它 问题是,如果我想有这样的行为,我需要每次创建一个新的lua_状态,然后每次打开库,然后每次解析脚本文件,这似乎是非常不优化的 加载库可能是一个相当轻量级的操作(我假设),但解析脚本可能不是 有没有一种方法可以重置Lua脚本的状态(即清除用户代码定义的变量),而无

我有一个运行Lua脚本的应用程序。每个Lua脚本可能会运行几次。有些脚本甚至可能在每次按键时运行

我希望在每次运行之间“重置”这些脚本。也就是说,如果用户设置了一个变量Foo,那么Foo在下次运行时不应该存在于脚本中,直到用户再次定义它

问题是,如果我想有这样的行为,我需要每次创建一个新的lua_状态,然后每次打开库,然后每次解析脚本文件,这似乎是非常不优化的

加载库可能是一个相当轻量级的操作(我假设),但解析脚本可能不是

有没有一种方法可以重置Lua脚本的状态(即清除用户代码定义的变量),而无需创建新的Lua_状态并重新分析整个Lua脚本文件?我只希望脚本文件在应用程序启动时被解析一次,因为它们在运行时不会被修改

谢谢。:)

编辑:我找到了这个主题,但没有详细说明:

编辑:卢厄·塞特芬夫似乎与此有关。我再挖一点


编辑:从lua 5.2开始,似乎不再有lua_setfenv了。由于我使用的是5.3,因此我必须设置环境(即存储变量的隐藏表nammed _ENV),然后重新加载所有内容,这是我不想做的…

您不能清除lua_状态吗?删除所有线程和手动设置的全局线程。您可能需要将用户环境与全局环境分开。

上次我研究这个问题时,不幸的是,答案是否定的

您还需要记住,Lua可能会调用库,这些库可能会打开文件,
malloc()
内存等,任何“重置”都需要处理关闭这些文件、释放内存等问题

作为“重置”Lua状态的替代方法,您可以简单地组织代码,使其不需要重置;这显然需要以特定的方式编写Lua代码。一种方法是坚持您的Lua代码完全(或几乎完全)包含在函数中,并为每个操作调用一个或多个函数。函数外部的代码可能(例如)返回一个Lua表,该表包含用于调用特定入口点的引用;这只会被调用一次。调用函数时,函数将在其自身之后清除,包括清除任何库分配的项、打开的文件等。应避免使用全局变量(除非是常量)。我们成功地使用这种方法来确保Lua只被解析一次,入口点被确定一次,但是相对较小的函数可以很快地被调用,并且开销很小

在您建议的注释中,您可以将Lua代码以词汇形式包装在函数块中。我认为这不如上述方法灵活,并且有以下缺点:

  • 您失去了执行“一次性初始化”的机会(例如,从磁盘读取固定常数)

  • 如果用户插入(例如)一个不匹配的
    end。。。函数B()
    在其代码中

  • 您将自己约束到每个Lua状态的一个入口点


这确实意味着Lua代码必须以不同的方式编写(本质上,Lua编码器是以所需的形式提供代码)。一种可能的解决方法是使用一个固定的框架来实现这一点,并且
要求将代码中的
称为库。我没有尝试过这种方法。

如果您想确保每次脚本调用时lua_状态相同,您也可以尝试以下适用于我的案例的方法:

  • 将自定义内存分配器传递给lua_newstate,lua_newstate从内存池分配内存
  • 在解析脚本之后,在第一次“运行”之前,在其他一些内存位置创建内存池的备份
  • 每次“运行”后,从备份中恢复原始位置的内存池
请注意,这只考虑Lua数据结构中完全包含的资源,而不考虑以任何方式从Lua或Lua库引用的“外部”资源(例如文件描述符、用户数据等)

因此,在我的例子中,我还通过替换globals表,将脚本编写器的能力限制为仅提供上述使用中认为安全的操作的沙箱


使用这种方法,重置基本上归结为每次“运行”后的一些
memcpy
调用,因此需要多长时间来复制Lua结构用于脚本的内存。

是“用户环境”从lua_州分离?有一个全局环境,其中包含“表”和“打印”等内容。根据实现情况,这也是用户环境。如果用户执行
a=123
,则全局环境中有一个字段a。你可以用一个简单的getfenv/setfenv(或_ENV)将其C端(我不知道如何)或Lua端分开,创建一个新的环境,其中一个元字段u索引指向旧的。谢谢你的帮助。如果某些库正在分配资源,那么在删除所有用户变量时,这些资源不应该自动释放/垃圾收集吗?此外,我是否可以在运行脚本之前手动删除_ENV中的所有值,并执行类似lua_settop(0)的操作来重置堆栈?还有一个问题可能会以另一种方式解决我的问题:如果所有用户创建的变量都是使用local定义的,然后在解析它之前将脚本包装到函数中,该怎么办?当函数结束时,它的所有局部变量都会被破坏,对吗?@Virus721-当然,如果程序有效地重置了自己(或者说不需要重置),那就可以了。我们所做的非常相似