【问题标题】:Lua best practice close variable with popen()Lua 最佳实践使用 popen() 关闭变量
【发布时间】:2021-02-17 05:27:30
【问题描述】:

我是 Lua 新手,对 Lua 中的内存管理有疑问。

问题1)在使用io.popen()调用函数时,我看到很多Lua程序员在使用popen()函数后写了一个close语句。我想知道这是什么原因?比如演示看这段代码:

handle = io.popen("ls -a")
output = handle:read("*all")
handle:close()
print(output)

handle = io.popen("date")
output = handle:read("*all")
handle:close()
print(output)

我听说 Lua 可以自己管理内存。那么我真的需要像上面那样写handle:close吗?如果我只是忽略handle:close() 语句并像这样写它,内存会发生什么?

handle = io.popen("ls -a")
handle = io.popen("date")
output = handle:read("*all")

问题2)从question 1中的代码来看,在内存使用方面,我们可以将handle:close()语句写在最后一行而不是这样吗?:

handle = io.popen("ls -a")
output = handle:read("*all")
-- handle:close() -- dont close it yet do at the end
print(output)
handle = io.popen("date") -- this use the same variable `handle` previously
output = handle:read("*all")
handle:close()  -- only one statement to close all above
print(output)

您可以看到,当我使用io.popen 时,我没有从第一个语句中关闭它,但我在最后关闭它,这是否会使程序变慢,因为我最后只使用一个 close 语句关闭它?

【问题讨论】:

  • file:close() 与内存管理无关。您应该尽快关闭打开的文件句柄,因为它是非常有限的操作系统资源。您不能同时打开很多文件。
  • 你的意思是io.popen 是一个文件处理方法吗?我的意思是io.popen 不是io.open
  • io.popen 创建一个管道并为您提供该管道的句柄。这是一个类似文件的句柄。
  • Lua 确实会在最近的 GC 周期中自动关闭文件处理程序,但它被不可预测地推迟了。它可能会在值未使用数小时后发生。
  • 您仍然需要关闭句柄。在第二个示例中,您只是用新句柄重新分配变量,使旧句柄无法访问。 GC 可能会明智地清除参考内存,但操作系统在进程完成之前无法知道这一点......

标签: lua


【解决方案1】:

问题 1

在这种情况下close 不是出于内存原因,而是为了关闭文件。当一个文件句柄被收集时,它会自动关闭,但是如果一个程序没有产生太多垃圾(一些程序员专门为此优化),GC可能会在程序完成文件处理后的很长一段时间内不会运行并且文件将保持打开状态。

另外,如果变量留在作用域内,那么在作用域结束之前,GC 根本无法收集它,这可能需要很长时间。

问题 2

那是行不通的。方法是在值上调用的,而不是在变量上,所以当你给一个变量分配一个新值时,旧的值就会消失。对新值调用方法不会影响以前存储在变量中的任何其他值。

【讨论】:

    【解决方案2】:

    当垃圾收集器开始收集文件时,Lua 会自动关闭文件句柄。

    Lua Manual 5.4: file:close

    关闭文件。请注意,当文件的句柄被垃圾回收时,文件会自动关闭,但这会花费不可预测的时间。

    但是,最好在处理完句柄后自己关闭句柄,这是因为 GC 会花费未知的时间来完成它。

    这不是内存问题,而是打开文件句柄的资源更加有限,例如 Windows 机器上的 512,一个用于运行在其上的所有应用程序的小池。


    至于第二个问题,当你重新分配一个变量时AND没有其他对前一个值的剩余引用,该值最终会被 GC 收集。

    【讨论】:

    • question 2 怎么样?每次调用都使用相同的变量,然后我在最后关闭它,这类似于每行关闭它吗?
    • @KalibZen 重新分配变量只会使旧值无法访问,因此符合 gc 条件
    • @codeflush.dev 好的,这意味着,我需要在使用后立即关闭它,不推荐使用第二个示例。非常感谢您提供这些有用的信息,尤其是关于参考的信息。我认为使用相同的变量会破坏它。我的代码中有太多的结束语句。有没有一种方法可以自动关闭每个句柄,而无需编写每个调用的关闭语句。由于我使用了很多 popen 函数,因此使用 close 语句使代码变得混乱。
    • @KalibZen 您可以创建一个函数来包装popen readclose 调用并返回读取结果,这是您无论如何都应该做的事情,前提是保持代码干燥。
    • @KalibZen 这应该可以满足您的需求pastebin.com/pzkUditY
    猜你喜欢
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    • 2013-10-02
    • 2010-10-06
    • 2011-10-28
    • 2010-09-10
    • 2011-10-11
    相关资源
    最近更新 更多