LuaTeX 手册并没有提供太多关于确切细节的信息,只是说需要确保没有任何悬空指针仍然引用节点(位置)。对于简单节点来说,情况可能如此,但调整节点已经让我怀疑我的理解了。
这种类型的节点有一个字段head
指向另一个保存“vadjust”垂直列表的节点。所以我简单的假设是,如果我这样做
local adjust = node.getfield(p, "head") -- save the vlist
node.free(p)
我没事,但结果发现我代码中的所有指针都乱了。相反,我必须先明确地做
node.setfield(p, "head", nil)
在释放节点之前,防止发生不好的事情。如果字段值不为 nil,那么到底出了什么问题,或者函数对字段值做了什么,我无法通过反复试验来确定。
所以我的问题是:谁可以准确地解释这个命令发生了什么以及/或在哪里可以找到它(即,假设它是一种可读的格式,它的来源在哪里)?
问题的另一部分是,当释放具有类似结构的其他节点时会发生什么,例如粘合节点(具有到粘合规范节点的链接等)?
答案1
这是试图记录如何我理解它。它并不意味着权威。LuaTeX(节点端)没有任何自动垃圾收集。如果你丢失了指向节点的指针,它将在 TeX 的内存中丢失并占用空间。node.free()
你可以释放一个节点及其所有子节点。也就是说,如果你有一个hlist
节点,node.free()
将删除该节点和列表的节点(其内容)。它不会删除当前节点列表中的下一个节点。让我添加几个例子:
简单示例
local a = node.new("glyph")
a.char = 97
local b = node.new("glyph")
b.char = 98
node.insert_after(a,a,b)
node.free(b)
-- error: ! Attempt to double-free glyph (b) node 103, ignored.
node.free(b)
这应该是显而易见的。两次释放节点不是一件好事。
警告。a
仍然指向某物。如果你从 开始遍历节点列表a
,LuaTeX 会出错。
内部带有字形的水平盒子
local a = node.new("glyph")
a.char = 97
b = node.hpack(a)
node.free(b)
-- ! Attempt to double-free glyph (a) node 97, ignored.
node.free(a)
这里,a
是节点的子节点之一,因此当释放b
时,a 也会从内存中删除。b
胶水及胶水规格
现在举一个可能不太明显的例子:
local spec = node.new("glue_spec")
spec.width = 1000
spec.stretch = 1
local a = node.new("glue")
a.spec = spec
local b = node.new("glue")
b.spec = spec
node.free(a)
-- error:
-- ! Attempt to double-free glue_spec node 85, ignored.
node.free(b)
再次:节点a
从内存中删除,然后子节点spec
被释放。因此(我觉得有点惊讶)b 的子节点也从内存中删除了……
连字符(仅两个字符:f 和 i)
结扎前:
结扎后:
local a = node.new("glyph")
a.char = 102
a.font = 15
local b = node.new("glyph")
b.char = 105
b.font = 15
node.insert_after(a,a,b)
a = node.ligaturing(a)
local c = a.components
node.free(a)
node.free(c)
node.free(a)
删除组件,因此删除c
会导致错误。