luatex 的 node.free 到底删除了什么?

luatex 的 node.free 到底删除了什么?

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 会出错。

内部带有字形的水平盒子

hpack 节点列表

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会导致错误。

相关内容